From 6fa24363ac4db37ee4485535d6f7b57bec6d0069 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Sat, 12 Oct 2024 01:59:03 +0000 Subject: [PATCH 001/232] chore(deps): weekly `cargo update` Locking 35 packages to latest compatible versions Updating alloy-dyn-abi v0.8.6 -> v0.8.7 Updating alloy-json-abi v0.8.6 -> v0.8.7 Updating alloy-primitives v0.8.6 -> v0.8.7 Updating alloy-sol-macro v0.8.6 -> v0.8.7 Updating alloy-sol-macro-expander v0.8.6 -> v0.8.7 Updating alloy-sol-macro-input v0.8.6 -> v0.8.7 Updating alloy-sol-type-parser v0.8.6 -> v0.8.7 Updating alloy-sol-types v0.8.6 -> v0.8.7 Updating async-compression v0.4.13 -> v0.4.14 Updating aws-sdk-kms v1.46.0 -> v1.47.0 Updating aws-sdk-sso v1.45.0 -> v1.46.0 Updating aws-sdk-ssooidc v1.46.0 -> v1.47.0 Updating aws-sdk-sts v1.45.0 -> v1.46.0 Updating aws-smithy-runtime v1.7.1 -> v1.7.2 Updating cc v1.1.28 -> v1.1.30 Updating clap v4.5.19 -> v4.5.20 Updating clap_builder v4.5.19 -> v4.5.20 Updating clap_complete v4.5.32 -> v4.5.33 Updating derive_builder v0.20.1 -> v0.20.2 Updating derive_builder_core v0.20.1 -> v0.20.2 Updating derive_builder_macro v0.20.1 -> v0.20.2 Updating js-sys v0.3.70 -> v0.3.72 Updating lru v0.12.4 -> v0.12.5 Updating newtype-uuid v1.1.0 -> v1.1.2 Updating proc-macro2 v1.0.86 -> v1.0.87 Updating scc v2.2.0 -> v2.2.1 Updating sdd v3.0.3 -> v3.0.4 Updating syn-solidity v0.8.6 -> v0.8.7 Updating wasm-bindgen v0.2.93 -> v0.2.95 Updating wasm-bindgen-backend v0.2.93 -> v0.2.95 Updating wasm-bindgen-futures v0.4.43 -> v0.4.45 Updating wasm-bindgen-macro v0.2.93 -> v0.2.95 Updating wasm-bindgen-macro-support v0.2.93 -> v0.2.95 Updating wasm-bindgen-shared v0.2.93 -> v0.2.95 Updating web-sys v0.3.70 -> v0.3.72 note: pass `--verbose` to see 10 unchanged dependencies behind latest --- Cargo.lock | 148 ++++++++++++++++++++++++++--------------------------- 1 file changed, 73 insertions(+), 75 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0aec92430c11f..e597a7a91fd0b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -123,9 +123,9 @@ dependencies = [ [[package]] name = "alloy-dyn-abi" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1109c57718022ac84c194f775977a534e1b3969b405e55693a61c42187cc0612" +checksum = "f95d76a38cae906fd394a5afb0736aaceee5432efe76addfd71048e623e208af" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -200,9 +200,9 @@ dependencies = [ [[package]] name = "alloy-json-abi" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4cc0e59c803dd44d14fc0cfa9fea1f74cfa8fd9fb60ca303ced390c58c28d4e" +checksum = "03c66eec1acdd96b39b995b8f5ee5239bc0c871d62c527ae1ac9fd1d7fecd455" dependencies = [ "alloy-primitives", "alloy-sol-type-parser", @@ -260,9 +260,9 @@ dependencies = [ [[package]] name = "alloy-primitives" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a289ffd7448036f2f436b377f981c79ce0b2090877bad938d43387dc09931877" +checksum = "8ecb848c43f6b06ae3de2e4a67496cbbabd78ae87db0f1248934f15d76192c6a" dependencies = [ "alloy-rlp", "arbitrary", @@ -606,9 +606,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0409e3ba5d1de409997a7db8b8e9d679d52088c1dee042a85033affd3cadeab4" +checksum = "661c516eb1fa3294cc7f2fb8955b3b609d639c282ac81a4eedb14d3046db503a" dependencies = [ "alloy-sol-macro-expander", "alloy-sol-macro-input", @@ -620,9 +620,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro-expander" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a18372ef450d59f74c7a64a738f546ba82c92f816597fed1802ef559304c81f1" +checksum = "ecbabb8fc3d75a0c2cea5215be22e7a267e3efde835b0f2a8922f5e3f5d47683" dependencies = [ "alloy-json-abi", "alloy-sol-macro-input", @@ -639,9 +639,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro-input" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7bad89dd0d5f109e8feeaf787a9ed7a05a91a9a0efc6687d147a70ebca8eff7" +checksum = "16517f2af03064485150d89746b8ffdcdbc9b6eeb3d536fb66efd7c2846fbc75" dependencies = [ "alloy-json-abi", "const-hex", @@ -656,9 +656,9 @@ dependencies = [ [[package]] name = "alloy-sol-type-parser" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbd3548d5262867c2c4be6223fe4f2583e21ade0ca1c307fd23bc7f28fca479e" +checksum = "c07ebb0c1674ff8cbb08378d7c2e0e27919d2a2dae07ad3bca26174deda8d389" dependencies = [ "serde", "winnow", @@ -666,9 +666,9 @@ dependencies = [ [[package]] name = "alloy-sol-types" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4aa666f1036341b46625e72bd36878bf45ad0185f1b88601223e1ec6ed4b72b1" +checksum = "8e448d879903624863f608c552d10efb0e0905ddbee98b0049412799911eb062" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -1129,9 +1129,9 @@ dependencies = [ [[package]] name = "async-compression" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e614738943d3f68c628ae3dbce7c3daffb196665f82f8c8ea6b65de73c79429" +checksum = "998282f8f49ccd6116b0ed8a4de0fbd3151697920e7c7533416d6e25e76434a7" dependencies = [ "flate2", "futures-core", @@ -1321,9 +1321,9 @@ dependencies = [ [[package]] name = "aws-sdk-kms" -version = "1.46.0" +version = "1.47.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33590e8d45206fdc4273ded8a1f292bcceaadd513037aa790fc67b237bc30ee" +checksum = "564a597a3c71a957d60a2e4c62c93d78ee5a0d636531e15b760acad983a5c18e" dependencies = [ "aws-credential-types", "aws-runtime", @@ -1343,9 +1343,9 @@ dependencies = [ [[package]] name = "aws-sdk-sso" -version = "1.45.0" +version = "1.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33ae899566f3d395cbf42858e433930682cc9c1889fa89318896082fef45efb" +checksum = "0dc2faec3205d496c7e57eff685dd944203df7ce16a4116d0281c44021788a7b" dependencies = [ "aws-credential-types", "aws-runtime", @@ -1365,9 +1365,9 @@ dependencies = [ [[package]] name = "aws-sdk-ssooidc" -version = "1.46.0" +version = "1.47.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f39c09e199ebd96b9f860b0fce4b6625f211e064ad7c8693b72ecf7ef03881e0" +checksum = "c93c241f52bc5e0476e259c953234dab7e2a35ee207ee202e86c0095ec4951dc" dependencies = [ "aws-credential-types", "aws-runtime", @@ -1387,9 +1387,9 @@ dependencies = [ [[package]] name = "aws-sdk-sts" -version = "1.45.0" +version = "1.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d95f93a98130389eb6233b9d615249e543f6c24a68ca1f109af9ca5164a8765" +checksum = "b259429be94a3459fa1b00c5684faee118d74f9577cc50aebadc36e507c63b5f" dependencies = [ "aws-credential-types", "aws-runtime", @@ -1483,9 +1483,9 @@ dependencies = [ [[package]] name = "aws-smithy-runtime" -version = "1.7.1" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1ce695746394772e7000b39fe073095db6d45a862d0767dd5ad0ac0d7f8eb87" +checksum = "a065c0fe6fdbdf9f11817eb68582b2ab4aff9e9c39e986ae48f7ec576c6322db" dependencies = [ "aws-smithy-async", "aws-smithy-http", @@ -1991,9 +1991,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.28" +version = "1.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e80e3b6a3ab07840e1cae9b0666a63970dc28e8ed5ffbcdacbfc760c281bfc1" +checksum = "b16803a61b81d9eabb7eae2588776c4c1e584b738ede45fdbb4c972cec1e9945" dependencies = [ "shlex", ] @@ -2105,9 +2105,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.19" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7be5744db7978a28d9df86a214130d106a89ce49644cbc4e3f0c22c3fba30615" +checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" dependencies = [ "clap_builder", "clap_derive", @@ -2115,9 +2115,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.19" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5fbc17d3ef8278f55b282b2a2e75ae6f6c7d4bb70ed3d0382375104bfafdb4b" +checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" dependencies = [ "anstream", "anstyle", @@ -2130,9 +2130,9 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.5.32" +version = "4.5.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74a01f4f9ee6c066d42a1c8dedf0dcddad16c72a8981a309d6398de3a75b0c39" +checksum = "9646e2e245bf62f45d39a0f3f36f1171ad1ea0d6967fd114bca72cb02a8fcdfb" dependencies = [ "clap", ] @@ -2663,18 +2663,18 @@ dependencies = [ [[package]] name = "derive_builder" -version = "0.20.1" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd33f37ee6a119146a1781d3356a7c26028f83d779b2e04ecd45fdc75c76877b" +checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" dependencies = [ "derive_builder_macro", ] [[package]] name = "derive_builder_core" -version = "0.20.1" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7431fa049613920234f22c47fdc33e6cf3ee83067091ea4277a3f8c4587aae38" +checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" dependencies = [ "darling", "proc-macro2", @@ -2684,9 +2684,9 @@ dependencies = [ [[package]] name = "derive_builder_macro" -version = "0.20.1" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4abae7035bf79b9877b779505d8cf3749285b80c43941eda66604841889451dc" +checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", "syn 2.0.79", @@ -4673,10 +4673,6 @@ name = "hashbrown" version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" -dependencies = [ - "ahash", - "allocator-api2", -] [[package]] name = "hashbrown" @@ -4684,6 +4680,8 @@ version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" dependencies = [ + "allocator-api2", + "equivalent", "foldhash", "serde", ] @@ -5280,9 +5278,9 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "js-sys" -version = "0.3.70" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" dependencies = [ "wasm-bindgen", ] @@ -5493,11 +5491,11 @@ dependencies = [ [[package]] name = "lru" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904" +checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" dependencies = [ - "hashbrown 0.14.5", + "hashbrown 0.15.0", ] [[package]] @@ -5753,9 +5751,9 @@ checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" [[package]] name = "newtype-uuid" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3526cb7c660872e401beaf3297f95f548ce3b4b4bdd8121b7c0713771d7c4a6e" +checksum = "4f4933943834e236c864a48aefdc2da43885dbd5eb77bff3ab20f31e0c3146f5" dependencies = [ "uuid 1.10.0", ] @@ -6661,9 +6659,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a" dependencies = [ "unicode-ident", ] @@ -7602,9 +7600,9 @@ dependencies = [ [[package]] name = "scc" -version = "2.2.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836f1e0f4963ef5288b539b643b35e043e76a32d0f4e47e67febf69576527f50" +checksum = "553f8299af7450cda9a52d3a370199904e7a46b5ffd1bef187c4a6af3bb6db69" dependencies = [ "sdd", ] @@ -7678,9 +7676,9 @@ dependencies = [ [[package]] name = "sdd" -version = "3.0.3" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a7b59a5d9b0099720b417b6325d91a52cbf5b3dcb5041d864be53eefa58abc" +checksum = "49c1eeaf4b6a87c7479688c6d52b9f1153cedd3c489300564f932b065c6eab95" [[package]] name = "sec1" @@ -8343,9 +8341,9 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3a850d65181df41b83c6be01a7d91f5e9377c43d48faa5af7d95816f437f5a3" +checksum = "20e7b52ad118b2153644eea95c6fc740b6c1555b2344fdab763fc9de4075f665" dependencies = [ "paste", "proc-macro2", @@ -9252,9 +9250,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" dependencies = [ "cfg-if", "once_cell", @@ -9263,9 +9261,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" dependencies = [ "bumpalo", "log", @@ -9278,9 +9276,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.43" +version = "0.4.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" +checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" dependencies = [ "cfg-if", "js-sys", @@ -9290,9 +9288,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -9300,9 +9298,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", @@ -9313,9 +9311,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" [[package]] name = "wasm-streams" @@ -9395,9 +9393,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.70" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" +checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" dependencies = [ "js-sys", "wasm-bindgen", From c46fd9289e8a3d21a95db83163675fce7d7521d8 Mon Sep 17 00:00:00 2001 From: Legion's <64915515+Dargon789@users.noreply.github.com> Date: Fri, 11 Oct 2024 19:09:52 -0700 Subject: [PATCH 002/232] Create codeql.yml Signed-off-by: Legion's <64915515+Dargon789@users.noreply.github.com> --- .github/workflows/codeql.yml | 92 ++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 .github/workflows/codeql.yml diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000000000..5bf742c565e0f --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,92 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL Advanced" + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + schedule: + - cron: '25 9 * * 3' + +jobs: + analyze: + name: Analyze (${{ matrix.language }}) + # Runner size impacts CodeQL analysis time. To learn more, please see: + # - https://gh.io/recommended-hardware-resources-for-running-codeql + # - https://gh.io/supported-runners-and-hardware-resources + # - https://gh.io/using-larger-runners (GitHub.com only) + # Consider using larger runners or machines with greater resources for possible analysis time improvements. + runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} + permissions: + # required for all workflows + security-events: write + + # required to fetch internal or private CodeQL packs + packages: read + + # only required for workflows in private repositories + actions: read + contents: read + + strategy: + fail-fast: false + matrix: + include: + - language: python + build-mode: none + # CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift' + # Use `c-cpp` to analyze code written in C, C++ or both + # Use 'java-kotlin' to analyze code written in Java, Kotlin or both + # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both + # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis, + # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning. + # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how + # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ${{ matrix.language }} + build-mode: ${{ matrix.build-mode }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + + # If the analyze step fails for one of the languages you are analyzing with + # "We were unable to automatically build your code", modify the matrix above + # to set the build mode to "manual" for that language. Then modify this step + # to build your code. + # ℹ️ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + - if: matrix.build-mode == 'manual' + shell: bash + run: | + echo 'If you are using a "manual" build mode for one or more of the' \ + 'languages you are analyzing, replace this with the commands to build' \ + 'your code, for example:' + echo ' make bootstrap' + echo ' make release' + exit 1 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + with: + category: "/language:${{matrix.language}}" From f4c98067e8f66d0b4cc8634971412e7f065d79d5 Mon Sep 17 00:00:00 2001 From: Legion's <64915515+Dargon789@users.noreply.github.com> Date: Fri, 11 Oct 2024 22:53:00 -0700 Subject: [PATCH 003/232] Update issue templates --- .github/ISSUE_TEMPLATE/bug_report.md | 38 +++++++++++++++++++++++ .github/ISSUE_TEMPLATE/custom.md | 10 ++++++ .github/ISSUE_TEMPLATE/feature_request.md | 20 ++++++++++++ 3 files changed, 68 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/custom.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000000000..dd84ea7824f11 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,38 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Desktop (please complete the following information):** + - OS: [e.g. iOS] + - Browser [e.g. chrome, safari] + - Version [e.g. 22] + +**Smartphone (please complete the following information):** + - Device: [e.g. iPhone6] + - OS: [e.g. iOS8.1] + - Browser [e.g. stock browser, safari] + - Version [e.g. 22] + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/custom.md b/.github/ISSUE_TEMPLATE/custom.md new file mode 100644 index 0000000000000..48d5f81fa4229 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/custom.md @@ -0,0 +1,10 @@ +--- +name: Custom issue template +about: Describe this issue template's purpose here. +title: '' +labels: '' +assignees: '' + +--- + + diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000000000..bbcbbe7d61558 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. From 4e543f759a28b7d944ca88d71982a23ace15c58d Mon Sep 17 00:00:00 2001 From: Legion's <64915515+Dargon789@users.noreply.github.com> Date: Fri, 11 Oct 2024 22:54:56 -0700 Subject: [PATCH 004/232] Create apisec-scan.yml Signed-off-by: Legion's <64915515+Dargon789@users.noreply.github.com> --- .github/workflows/apisec-scan.yml | 71 +++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 .github/workflows/apisec-scan.yml diff --git a/.github/workflows/apisec-scan.yml b/.github/workflows/apisec-scan.yml new file mode 100644 index 0000000000000..d719efe66e0e2 --- /dev/null +++ b/.github/workflows/apisec-scan.yml @@ -0,0 +1,71 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +# APIsec addresses the critical need to secure APIs before they reach production. +# APIsec provides the industry’s only automated and continuous API testing platform that uncovers security vulnerabilities and logic flaws in APIs. +# Clients rely on APIsec to evaluate every update and release, ensuring that no APIs go to production with vulnerabilities. + +# How to Get Started with APIsec.ai +# 1. Schedule a demo at https://www.apisec.ai/request-a-demo . +# +# 2. Register your account at https://cloud.apisec.ai/#/signup . +# +# 3. Register your API . See the video (https://www.youtube.com/watch?v=MK3Xo9Dbvac) to get up and running with APIsec quickly. +# +# 4. Get GitHub Actions scan attributes from APIsec Project -> Configurations -> Integrations -> CI-CD -> GitHub Actions +# +# apisec-run-scan +# +# This action triggers the on-demand scans for projects registered in APIsec. +# If your GitHub account allows code scanning alerts, you can then upload the sarif file generated by this action to show the scan findings. +# Else you can view the scan results from the project home page in APIsec Platform. +# The link to view the scan results is also displayed on the console on successful completion of action. + +# This is a starter workflow to help you get started with APIsec-Scan Actions + +name: APIsec + +# Controls when the workflow will run +on: + # Triggers the workflow on push or pull request events but only for the "master" branch + # Customize trigger events based on your DevSecOps processes. + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + schedule: + - cron: '42 12 * * 4' + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + + +permissions: + contents: read + +jobs: + + Trigger_APIsec_scan: + permissions: + security-events: write # for github/codeql-action/upload-sarif to upload SARIF results + actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status + runs-on: ubuntu-latest + + steps: + - name: APIsec scan + uses: apisec-inc/apisec-run-scan@025432089674a28ba8fb55f8ab06c10215e772ea + with: + # The APIsec username with which the scans will be executed + apisec-username: ${{ secrets.apisec_username }} + # The Password of the APIsec user with which the scans will be executed + apisec-password: ${{ secrets.apisec_password}} + # The name of the project for security scan + apisec-project: "VAmPI" + # The name of the sarif format result file The file is written only if this property is provided. + sarif-result-file: "apisec-results.sarif" + - name: Import results + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: ./apisec-results.sarif From 7843e74f82f95ebe60768b2bfa5a05adf9f27faa Mon Sep 17 00:00:00 2001 From: Dargon789 Date: Mon, 28 Oct 2024 03:57:33 +0700 Subject: [PATCH 005/232] add remix_tests project --- .deps/remix-tests/remix_accounts.sol | 39 +++++ .deps/remix-tests/remix_tests.sol | 225 +++++++++++++++++++++++++++ 2 files changed, 264 insertions(+) create mode 100644 .deps/remix-tests/remix_accounts.sol create mode 100644 .deps/remix-tests/remix_tests.sol diff --git a/.deps/remix-tests/remix_accounts.sol b/.deps/remix-tests/remix_accounts.sol new file mode 100644 index 0000000000000..c1c42dc96b93e --- /dev/null +++ b/.deps/remix-tests/remix_accounts.sol @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity >=0.4.22 <0.9.0; + +library TestsAccounts { + function getAccount(uint index) pure public returns (address) { + address[15] memory accounts; + accounts[0] = 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4; + + accounts[1] = 0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2; + + accounts[2] = 0x4B20993Bc481177ec7E8f571ceCaE8A9e22C02db; + + accounts[3] = 0x78731D3Ca6b7E34aC0F824c42a7cC18A495cabaB; + + accounts[4] = 0x617F2E2fD72FD9D5503197092aC168c91465E7f2; + + accounts[5] = 0x17F6AD8Ef982297579C203069C1DbfFE4348c372; + + accounts[6] = 0x5c6B0f7Bf3E7ce046039Bd8FABdfD3f9F5021678; + + accounts[7] = 0x03C6FcED478cBbC9a4FAB34eF9f40767739D1Ff7; + + accounts[8] = 0x1aE0EA34a72D944a8C7603FfB3eC30a6669E454C; + + accounts[9] = 0x0A098Eda01Ce92ff4A4CCb7A4fFFb5A43EBC70DC; + + accounts[10] = 0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c; + + accounts[11] = 0x14723A09ACff6D2A60DcdF7aA4AFf308FDDC160C; + + accounts[12] = 0x4B0897b0513fdC7C541B6d9D7E929C4e5364D2dB; + + accounts[13] = 0x583031D1113aD414F02576BD6afaBfb302140225; + + accounts[14] = 0xdD870fA1b7C4700F2BD7f44238821C26f7392148; +return accounts[index]; + } +} diff --git a/.deps/remix-tests/remix_tests.sol b/.deps/remix-tests/remix_tests.sol new file mode 100644 index 0000000000000..b8b9960362203 --- /dev/null +++ b/.deps/remix-tests/remix_tests.sol @@ -0,0 +1,225 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity >=0.4.22 <0.9.0; + +library Assert { + + event AssertionEvent( + bool passed, + string message, + string methodName + ); + + event AssertionEventUint( + bool passed, + string message, + string methodName, + uint256 returned, + uint256 expected + ); + + event AssertionEventInt( + bool passed, + string message, + string methodName, + int256 returned, + int256 expected + ); + + event AssertionEventBool( + bool passed, + string message, + string methodName, + bool returned, + bool expected + ); + + event AssertionEventAddress( + bool passed, + string message, + string methodName, + address returned, + address expected + ); + + event AssertionEventBytes32( + bool passed, + string message, + string methodName, + bytes32 returned, + bytes32 expected + ); + + event AssertionEventString( + bool passed, + string message, + string methodName, + string returned, + string expected + ); + + event AssertionEventUintInt( + bool passed, + string message, + string methodName, + uint256 returned, + int256 expected + ); + + event AssertionEventIntUint( + bool passed, + string message, + string methodName, + int256 returned, + uint256 expected + ); + + function ok(bool a, string memory message) public returns (bool result) { + result = a; + emit AssertionEvent(result, message, "ok"); + } + + function equal(uint256 a, uint256 b, string memory message) public returns (bool result) { + result = (a == b); + emit AssertionEventUint(result, message, "equal", a, b); + } + + function equal(int256 a, int256 b, string memory message) public returns (bool result) { + result = (a == b); + emit AssertionEventInt(result, message, "equal", a, b); + } + + function equal(bool a, bool b, string memory message) public returns (bool result) { + result = (a == b); + emit AssertionEventBool(result, message, "equal", a, b); + } + + // TODO: only for certain versions of solc + //function equal(fixed a, fixed b, string message) public returns (bool result) { + // result = (a == b); + // emit AssertionEvent(result, message); + //} + + // TODO: only for certain versions of solc + //function equal(ufixed a, ufixed b, string message) public returns (bool result) { + // result = (a == b); + // emit AssertionEvent(result, message); + //} + + function equal(address a, address b, string memory message) public returns (bool result) { + result = (a == b); + emit AssertionEventAddress(result, message, "equal", a, b); + } + + function equal(bytes32 a, bytes32 b, string memory message) public returns (bool result) { + result = (a == b); + emit AssertionEventBytes32(result, message, "equal", a, b); + } + + function equal(string memory a, string memory b, string memory message) public returns (bool result) { + result = (keccak256(abi.encodePacked(a)) == keccak256(abi.encodePacked(b))); + emit AssertionEventString(result, message, "equal", a, b); + } + + function notEqual(uint256 a, uint256 b, string memory message) public returns (bool result) { + result = (a != b); + emit AssertionEventUint(result, message, "notEqual", a, b); + } + + function notEqual(int256 a, int256 b, string memory message) public returns (bool result) { + result = (a != b); + emit AssertionEventInt(result, message, "notEqual", a, b); + } + + function notEqual(bool a, bool b, string memory message) public returns (bool result) { + result = (a != b); + emit AssertionEventBool(result, message, "notEqual", a, b); + } + + // TODO: only for certain versions of solc + //function notEqual(fixed a, fixed b, string message) public returns (bool result) { + // result = (a != b); + // emit AssertionEvent(result, message); + //} + + // TODO: only for certain versions of solc + //function notEqual(ufixed a, ufixed b, string message) public returns (bool result) { + // result = (a != b); + // emit AssertionEvent(result, message); + //} + + function notEqual(address a, address b, string memory message) public returns (bool result) { + result = (a != b); + emit AssertionEventAddress(result, message, "notEqual", a, b); + } + + function notEqual(bytes32 a, bytes32 b, string memory message) public returns (bool result) { + result = (a != b); + emit AssertionEventBytes32(result, message, "notEqual", a, b); + } + + function notEqual(string memory a, string memory b, string memory message) public returns (bool result) { + result = (keccak256(abi.encodePacked(a)) != keccak256(abi.encodePacked(b))); + emit AssertionEventString(result, message, "notEqual", a, b); + } + + /*----------------- Greater than --------------------*/ + function greaterThan(uint256 a, uint256 b, string memory message) public returns (bool result) { + result = (a > b); + emit AssertionEventUint(result, message, "greaterThan", a, b); + } + + function greaterThan(int256 a, int256 b, string memory message) public returns (bool result) { + result = (a > b); + emit AssertionEventInt(result, message, "greaterThan", a, b); + } + // TODO: safely compare between uint and int + function greaterThan(uint256 a, int256 b, string memory message) public returns (bool result) { + if(b < int(0)) { + // int is negative uint "a" always greater + result = true; + } else { + result = (a > uint(b)); + } + emit AssertionEventUintInt(result, message, "greaterThan", a, b); + } + function greaterThan(int256 a, uint256 b, string memory message) public returns (bool result) { + if(a < int(0)) { + // int is negative uint "b" always greater + result = false; + } else { + result = (uint(a) > b); + } + emit AssertionEventIntUint(result, message, "greaterThan", a, b); + } + /*----------------- Lesser than --------------------*/ + function lesserThan(uint256 a, uint256 b, string memory message) public returns (bool result) { + result = (a < b); + emit AssertionEventUint(result, message, "lesserThan", a, b); + } + + function lesserThan(int256 a, int256 b, string memory message) public returns (bool result) { + result = (a < b); + emit AssertionEventInt(result, message, "lesserThan", a, b); + } + // TODO: safely compare between uint and int + function lesserThan(uint256 a, int256 b, string memory message) public returns (bool result) { + if(b < int(0)) { + // int is negative int "b" always lesser + result = false; + } else { + result = (a < uint(b)); + } + emit AssertionEventUintInt(result, message, "lesserThan", a, b); + } + + function lesserThan(int256 a, uint256 b, string memory message) public returns (bool result) { + if(a < int(0)) { + // int is negative int "a" always lesser + result = true; + } else { + result = (uint(a) < b); + } + emit AssertionEventIntUint(result, message, "lesserThan", a, b); + } +} From fb47f35432aabfcf203fa910709cc09597f16dab Mon Sep 17 00:00:00 2001 From: Legion's <64915515+Dargon789@users.noreply.github.com> Date: Tue, 19 Nov 2024 05:01:53 +0700 Subject: [PATCH 006/232] Update crates/config/src/compilation.rs Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> Signed-off-by: Legion's <64915515+Dargon789@users.noreply.github.com> --- crates/config/src/compilation.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/config/src/compilation.rs b/crates/config/src/compilation.rs index b4f00b91b0d92..cf5195a4bbf32 100644 --- a/crates/config/src/compilation.rs +++ b/crates/config/src/compilation.rs @@ -54,7 +54,7 @@ impl SettingsOverrides { #[derive(Debug, thiserror::Error)] pub enum RestrictionsError { - #[error("specified both exact and relative restrictions for {0}")] + #[error("invalid configuration: cannot specify both exact and relative restrictions for '{0}' - please choose only one type of restriction")] BothExactAndRelative(&'static str), } From 682c4f0966365d1cc3405eb415e4bf7fa4a41528 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Tue, 4 Mar 2025 05:16:42 +0700 Subject: [PATCH 007/232] Delete .github/workflows/apisec-scan.yml (#13) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .github/workflows/apisec-scan.yml | 71 ------------------------------- 1 file changed, 71 deletions(-) delete mode 100644 .github/workflows/apisec-scan.yml diff --git a/.github/workflows/apisec-scan.yml b/.github/workflows/apisec-scan.yml deleted file mode 100644 index d719efe66e0e2..0000000000000 --- a/.github/workflows/apisec-scan.yml +++ /dev/null @@ -1,71 +0,0 @@ -# This workflow uses actions that are not certified by GitHub. -# They are provided by a third-party and are governed by -# separate terms of service, privacy policy, and support -# documentation. - -# APIsec addresses the critical need to secure APIs before they reach production. -# APIsec provides the industry’s only automated and continuous API testing platform that uncovers security vulnerabilities and logic flaws in APIs. -# Clients rely on APIsec to evaluate every update and release, ensuring that no APIs go to production with vulnerabilities. - -# How to Get Started with APIsec.ai -# 1. Schedule a demo at https://www.apisec.ai/request-a-demo . -# -# 2. Register your account at https://cloud.apisec.ai/#/signup . -# -# 3. Register your API . See the video (https://www.youtube.com/watch?v=MK3Xo9Dbvac) to get up and running with APIsec quickly. -# -# 4. Get GitHub Actions scan attributes from APIsec Project -> Configurations -> Integrations -> CI-CD -> GitHub Actions -# -# apisec-run-scan -# -# This action triggers the on-demand scans for projects registered in APIsec. -# If your GitHub account allows code scanning alerts, you can then upload the sarif file generated by this action to show the scan findings. -# Else you can view the scan results from the project home page in APIsec Platform. -# The link to view the scan results is also displayed on the console on successful completion of action. - -# This is a starter workflow to help you get started with APIsec-Scan Actions - -name: APIsec - -# Controls when the workflow will run -on: - # Triggers the workflow on push or pull request events but only for the "master" branch - # Customize trigger events based on your DevSecOps processes. - push: - branches: [ "master" ] - pull_request: - branches: [ "master" ] - schedule: - - cron: '42 12 * * 4' - - # Allows you to run this workflow manually from the Actions tab - workflow_dispatch: - - -permissions: - contents: read - -jobs: - - Trigger_APIsec_scan: - permissions: - security-events: write # for github/codeql-action/upload-sarif to upload SARIF results - actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status - runs-on: ubuntu-latest - - steps: - - name: APIsec scan - uses: apisec-inc/apisec-run-scan@025432089674a28ba8fb55f8ab06c10215e772ea - with: - # The APIsec username with which the scans will be executed - apisec-username: ${{ secrets.apisec_username }} - # The Password of the APIsec user with which the scans will be executed - apisec-password: ${{ secrets.apisec_password}} - # The name of the project for security scan - apisec-project: "VAmPI" - # The name of the sarif format result file The file is written only if this property is provided. - sarif-result-file: "apisec-results.sarif" - - name: Import results - uses: github/codeql-action/upload-sarif@v3 - with: - sarif_file: ./apisec-results.sarif From 2a2b63d00c75aa243d19348de6515c475dd80b2c Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Tue, 4 Mar 2025 19:38:16 +0700 Subject: [PATCH 008/232] Update .github/ISSUE_TEMPLATE/bug_report.md Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .github/ISSUE_TEMPLATE/bug_report.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index dd84ea7824f11..43a59e29b9c29 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -25,7 +25,7 @@ If applicable, add screenshots to help explain your problem. **Desktop (please complete the following information):** - OS: [e.g. iOS] - - Browser [e.g. chrome, safari] + - Browser [e.g. Chrome, safari] - Version [e.g. 22] **Smartphone (please complete the following information):** From cfc4503bce8cac7d5a22ee3f1a235895e1a927c8 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Tue, 4 Mar 2025 21:13:23 +0700 Subject: [PATCH 009/232] Add .circleci/config.yml (#15) --- .circleci/config.yml | 31 ++++++++++++++ .github/workflows/apisec-scan.yml | 71 +++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+) create mode 100644 .circleci/config.yml create mode 100644 .github/workflows/apisec-scan.yml diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000000000..62291703e26a7 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,31 @@ +# Use the latest 2.1 version of CircleCI pipeline process engine. +# See: https://circleci.com/docs/configuration-reference +version: 2.1 + +# Define a job to be invoked later in a workflow. +# See: https://circleci.com/docs/jobs-steps/#jobs-overview & https://circleci.com/docs/configuration-reference/#jobs +jobs: + say-hello: + # Specify the execution environment. You can specify an image from Docker Hub or use one of our convenience images from CircleCI's Developer Hub. + # See: https://circleci.com/docs/executor-intro/ & https://circleci.com/docs/configuration-reference/#executor-job + docker: + # Specify the version you desire here + # See: https://circleci.com/developer/images/image/cimg/base + - image: cimg/base:current + + # Add steps to the job + # See: https://circleci.com/docs/jobs-steps/#steps-overview & https://circleci.com/docs/configuration-reference/#steps + steps: + # Checkout the code as the first step. + - checkout + - run: + name: "Say hello" + command: "echo Hello, World!" + +# Orchestrate jobs using workflows +# See: https://circleci.com/docs/workflows/ & https://circleci.com/docs/configuration-reference/#workflows +workflows: + say-hello-workflow: # This is the name of the workflow, feel free to change it to better match your workflow. + # Inside the workflow, you define the jobs you want to run. + jobs: + - say-hello \ No newline at end of file diff --git a/.github/workflows/apisec-scan.yml b/.github/workflows/apisec-scan.yml new file mode 100644 index 0000000000000..d719efe66e0e2 --- /dev/null +++ b/.github/workflows/apisec-scan.yml @@ -0,0 +1,71 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +# APIsec addresses the critical need to secure APIs before they reach production. +# APIsec provides the industry’s only automated and continuous API testing platform that uncovers security vulnerabilities and logic flaws in APIs. +# Clients rely on APIsec to evaluate every update and release, ensuring that no APIs go to production with vulnerabilities. + +# How to Get Started with APIsec.ai +# 1. Schedule a demo at https://www.apisec.ai/request-a-demo . +# +# 2. Register your account at https://cloud.apisec.ai/#/signup . +# +# 3. Register your API . See the video (https://www.youtube.com/watch?v=MK3Xo9Dbvac) to get up and running with APIsec quickly. +# +# 4. Get GitHub Actions scan attributes from APIsec Project -> Configurations -> Integrations -> CI-CD -> GitHub Actions +# +# apisec-run-scan +# +# This action triggers the on-demand scans for projects registered in APIsec. +# If your GitHub account allows code scanning alerts, you can then upload the sarif file generated by this action to show the scan findings. +# Else you can view the scan results from the project home page in APIsec Platform. +# The link to view the scan results is also displayed on the console on successful completion of action. + +# This is a starter workflow to help you get started with APIsec-Scan Actions + +name: APIsec + +# Controls when the workflow will run +on: + # Triggers the workflow on push or pull request events but only for the "master" branch + # Customize trigger events based on your DevSecOps processes. + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + schedule: + - cron: '42 12 * * 4' + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + + +permissions: + contents: read + +jobs: + + Trigger_APIsec_scan: + permissions: + security-events: write # for github/codeql-action/upload-sarif to upload SARIF results + actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status + runs-on: ubuntu-latest + + steps: + - name: APIsec scan + uses: apisec-inc/apisec-run-scan@025432089674a28ba8fb55f8ab06c10215e772ea + with: + # The APIsec username with which the scans will be executed + apisec-username: ${{ secrets.apisec_username }} + # The Password of the APIsec user with which the scans will be executed + apisec-password: ${{ secrets.apisec_password}} + # The name of the project for security scan + apisec-project: "VAmPI" + # The name of the sarif format result file The file is written only if this property is provided. + sarif-result-file: "apisec-results.sarif" + - name: Import results + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: ./apisec-results.sarif From 0b98e332b6f3bb02671adc4ffa4afcb47f7b7966 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Tue, 4 Mar 2025 22:48:54 +0700 Subject: [PATCH 010/232] Update apisec-scan.yml (#16) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .github/workflows/apisec-scan.yml | 79 +++++++------------------------ 1 file changed, 16 insertions(+), 63 deletions(-) diff --git a/.github/workflows/apisec-scan.yml b/.github/workflows/apisec-scan.yml index d719efe66e0e2..728b4819e7213 100644 --- a/.github/workflows/apisec-scan.yml +++ b/.github/workflows/apisec-scan.yml @@ -1,71 +1,24 @@ -# This workflow uses actions that are not certified by GitHub. -# They are provided by a third-party and are governed by -# separate terms of service, privacy policy, and support -# documentation. - -# APIsec addresses the critical need to secure APIs before they reach production. -# APIsec provides the industry’s only automated and continuous API testing platform that uncovers security vulnerabilities and logic flaws in APIs. -# Clients rely on APIsec to evaluate every update and release, ensuring that no APIs go to production with vulnerabilities. - -# How to Get Started with APIsec.ai -# 1. Schedule a demo at https://www.apisec.ai/request-a-demo . -# -# 2. Register your account at https://cloud.apisec.ai/#/signup . -# -# 3. Register your API . See the video (https://www.youtube.com/watch?v=MK3Xo9Dbvac) to get up and running with APIsec quickly. -# -# 4. Get GitHub Actions scan attributes from APIsec Project -> Configurations -> Integrations -> CI-CD -> GitHub Actions -# -# apisec-run-scan -# -# This action triggers the on-demand scans for projects registered in APIsec. -# If your GitHub account allows code scanning alerts, you can then upload the sarif file generated by this action to show the scan findings. -# Else you can view the scan results from the project home page in APIsec Platform. -# The link to view the scan results is also displayed on the console on successful completion of action. - # This is a starter workflow to help you get started with APIsec-Scan Actions - name: APIsec -# Controls when the workflow will run -on: - # Triggers the workflow on push or pull request events but only for the "master" branch - # Customize trigger events based on your DevSecOps processes. - push: - branches: [ "master" ] - pull_request: - branches: [ "master" ] - schedule: - - cron: '42 12 * * 4' - - # Allows you to run this workflow manually from the Actions tab - workflow_dispatch: - - -permissions: - contents: read +on: [push, pull_request] jobs: - Trigger_APIsec_scan: - permissions: - security-events: write # for github/codeql-action/upload-sarif to upload SARIF results - actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status runs-on: ubuntu-latest - steps: - - name: APIsec scan - uses: apisec-inc/apisec-run-scan@025432089674a28ba8fb55f8ab06c10215e772ea - with: - # The APIsec username with which the scans will be executed - apisec-username: ${{ secrets.apisec_username }} - # The Password of the APIsec user with which the scans will be executed - apisec-password: ${{ secrets.apisec_password}} - # The name of the project for security scan - apisec-project: "VAmPI" - # The name of the sarif format result file The file is written only if this property is provided. - sarif-result-file: "apisec-results.sarif" - - name: Import results - uses: github/codeql-action/upload-sarif@v3 - with: - sarif_file: ./apisec-results.sarif + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Run APIsec scan + uses: apisec-inc/apisec-run-scan@025432089674a28ba8fb55f8ab06c10215e772ea + with: + apisec-project: VAmPI + sarif-result-file: apisec-results.sarif + apisec-profile: Master + apisec-oas: false + # Ensure you provide valid credentials and host details + username: ${{ secrets.APISEC_USERNAME }} + password: ${{ secrets.APISEC_PASSWORD }} + host: ${{ secrets.APISEC_HOST }} + scanner: "default-scanner" From 1e98af9cec50931c37d0e04379f4481b4cb45d1b Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Wed, 5 Mar 2025 00:03:21 +0700 Subject: [PATCH 011/232] fix(forge): use float total cmp instead partial (#10005) (#17) fix(forge): use total cmp instead partial Co-authored-by: grandizzy <38490174+grandizzy@users.noreply.github.com> --- crates/cli/src/utils/suggestions.rs | 3 +-- crates/common/src/contracts.rs | 2 +- crates/forge/bin/cmd/snapshot.rs | 6 ++---- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/crates/cli/src/utils/suggestions.rs b/crates/cli/src/utils/suggestions.rs index 8f6d7f3cde092..a675ccae963c9 100644 --- a/crates/cli/src/utils/suggestions.rs +++ b/crates/cli/src/utils/suggestions.rs @@ -1,5 +1,4 @@ //! Helper functions for suggesting alternative values for a possibly erroneous user input. -use std::cmp::Ordering; /// Filters multiple strings from a given list of possible values which are similar /// to the passed in value `v` within a certain confidence by least confidence. @@ -17,7 +16,7 @@ where .map(|pv| (strsim::jaro_winkler(v, pv.as_ref()), pv.as_ref().to_owned())) .filter(|(similarity, _)| *similarity > 0.8) .collect(); - candidates.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap_or(Ordering::Equal)); + candidates.sort_by(|a, b| a.0.total_cmp(&b.0)); candidates.into_iter().map(|(_, pv)| pv).collect() } diff --git a/crates/common/src/contracts.rs b/crates/common/src/contracts.rs index 1e78751fde964..f9da7638fd422 100644 --- a/crates/common/src/contracts.rs +++ b/crates/common/src/contracts.rs @@ -147,7 +147,7 @@ impl ContractsByArtifact { None } }) - .min_by(|(score1, _), (score2, _)| score1.partial_cmp(score2).unwrap()) + .min_by(|(score1, _), (score2, _)| score1.total_cmp(score2)) .map(|(_, data)| data) } diff --git a/crates/forge/bin/cmd/snapshot.rs b/crates/forge/bin/cmd/snapshot.rs index 872a53138c8ee..aa0f0d94d95ee 100644 --- a/crates/forge/bin/cmd/snapshot.rs +++ b/crates/forge/bin/cmd/snapshot.rs @@ -373,9 +373,7 @@ fn diff(tests: Vec, snaps: Vec) -> Result<()> let mut overall_gas_change = 0i128; let mut overall_gas_used = 0i128; - diffs.sort_by(|a, b| { - a.gas_diff().abs().partial_cmp(&b.gas_diff().abs()).unwrap_or(Ordering::Equal) - }); + diffs.sort_by(|a, b| a.gas_diff().abs().total_cmp(&b.gas_diff().abs())); for diff in diffs { let gas_change = diff.gas_change(); @@ -401,7 +399,7 @@ fn diff(tests: Vec, snaps: Vec) -> Result<()> fn fmt_pct_change(change: f64) -> String { let change_pct = change * 100.0; - match change.partial_cmp(&0.0).unwrap_or(Ordering::Equal) { + match change.total_cmp(&0.0) { Ordering::Less => format!("{change_pct:.3}%").green().to_string(), Ordering::Equal => { format!("{change_pct:.3}%") From e45fdec11dd4bfea05b446395ca1a0ce90835160 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Wed, 5 Mar 2025 05:15:58 +0700 Subject: [PATCH 012/232] Update apisec-scan.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .github/workflows/apisec-scan.yml | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/.github/workflows/apisec-scan.yml b/.github/workflows/apisec-scan.yml index 728b4819e7213..5875cc28ae724 100644 --- a/.github/workflows/apisec-scan.yml +++ b/.github/workflows/apisec-scan.yml @@ -1,24 +1,27 @@ -# This is a starter workflow to help you get started with APIsec-Scan Actions name: APIsec -on: [push, pull_request] +on: + pull_request: + branches: + - main jobs: - Trigger_APIsec_scan: + scan: runs-on: ubuntu-latest steps: - - name: Checkout repository + - name: Checkout code uses: actions/checkout@v2 - name: Run APIsec scan uses: apisec-inc/apisec-run-scan@025432089674a28ba8fb55f8ab06c10215e772ea with: + apisec-username: ${{ secrets.APISEC_USERNAME }} + apisec-password: ${{ secrets.APISEC_PASSWORD }} apisec-project: VAmPI - sarif-result-file: apisec-results.sarif apisec-profile: Master + apisec-region: us-east-1 + sarif-result-file: apisec-results.sarif + apisec-email-report: true + apisec-fail-on-vuln-severity: critical apisec-oas: false - # Ensure you provide valid credentials and host details - username: ${{ secrets.APISEC_USERNAME }} - password: ${{ secrets.APISEC_PASSWORD }} - host: ${{ secrets.APISEC_HOST }} - scanner: "default-scanner" + apisec-openapi-spec-url: "https://example.com/openapi.json" From 02e28abdca0bf8c9acd833ab33b7a405198a7dea Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Wed, 5 Mar 2025 06:20:17 +0700 Subject: [PATCH 013/232] Revert "fix(forge): use float total cmp instead partial (#10005) (#17)" (#18) This reverts commit 1e98af9cec50931c37d0e04379f4481b4cb45d1b. --- crates/cli/src/utils/suggestions.rs | 3 ++- crates/common/src/contracts.rs | 2 +- crates/forge/bin/cmd/snapshot.rs | 6 ++++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/crates/cli/src/utils/suggestions.rs b/crates/cli/src/utils/suggestions.rs index a675ccae963c9..8f6d7f3cde092 100644 --- a/crates/cli/src/utils/suggestions.rs +++ b/crates/cli/src/utils/suggestions.rs @@ -1,4 +1,5 @@ //! Helper functions for suggesting alternative values for a possibly erroneous user input. +use std::cmp::Ordering; /// Filters multiple strings from a given list of possible values which are similar /// to the passed in value `v` within a certain confidence by least confidence. @@ -16,7 +17,7 @@ where .map(|pv| (strsim::jaro_winkler(v, pv.as_ref()), pv.as_ref().to_owned())) .filter(|(similarity, _)| *similarity > 0.8) .collect(); - candidates.sort_by(|a, b| a.0.total_cmp(&b.0)); + candidates.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap_or(Ordering::Equal)); candidates.into_iter().map(|(_, pv)| pv).collect() } diff --git a/crates/common/src/contracts.rs b/crates/common/src/contracts.rs index f9da7638fd422..1e78751fde964 100644 --- a/crates/common/src/contracts.rs +++ b/crates/common/src/contracts.rs @@ -147,7 +147,7 @@ impl ContractsByArtifact { None } }) - .min_by(|(score1, _), (score2, _)| score1.total_cmp(score2)) + .min_by(|(score1, _), (score2, _)| score1.partial_cmp(score2).unwrap()) .map(|(_, data)| data) } diff --git a/crates/forge/bin/cmd/snapshot.rs b/crates/forge/bin/cmd/snapshot.rs index aa0f0d94d95ee..872a53138c8ee 100644 --- a/crates/forge/bin/cmd/snapshot.rs +++ b/crates/forge/bin/cmd/snapshot.rs @@ -373,7 +373,9 @@ fn diff(tests: Vec, snaps: Vec) -> Result<()> let mut overall_gas_change = 0i128; let mut overall_gas_used = 0i128; - diffs.sort_by(|a, b| a.gas_diff().abs().total_cmp(&b.gas_diff().abs())); + diffs.sort_by(|a, b| { + a.gas_diff().abs().partial_cmp(&b.gas_diff().abs()).unwrap_or(Ordering::Equal) + }); for diff in diffs { let gas_change = diff.gas_change(); @@ -399,7 +401,7 @@ fn diff(tests: Vec, snaps: Vec) -> Result<()> fn fmt_pct_change(change: f64) -> String { let change_pct = change * 100.0; - match change.total_cmp(&0.0) { + match change.partial_cmp(&0.0).unwrap_or(Ordering::Equal) { Ordering::Less => format!("{change_pct:.3}%").green().to_string(), Ordering::Equal => { format!("{change_pct:.3}%") From 5931c87ca0200dcc7b7cd7dea7670086f9cb4d35 Mon Sep 17 00:00:00 2001 From: Legion's <64915515+Dargon789@users.noreply.github.com> Date: Wed, 5 Mar 2025 22:10:23 +0000 Subject: [PATCH 014/232] forge test openz --- .codesandbox/tasks.json | 7 ++++ .gitmodules | 6 +++ counter/.github/workflows/test.yml | 43 +++++++++++++++++++ counter/.gitignore | 14 +++++++ counter/README.md | 66 ++++++++++++++++++++++++++++++ counter/foundry.toml | 6 +++ counter/lib/forge-std | 1 + counter/lib/openzeppelin-contracts | 1 + counter/script/Counter.s.sol | 19 +++++++++ counter/src/Counter.sol | 14 +++++++ counter/test/Counter.t.sol | 24 +++++++++++ 11 files changed, 201 insertions(+) create mode 100644 .codesandbox/tasks.json create mode 100644 .gitmodules create mode 100644 counter/.github/workflows/test.yml create mode 100644 counter/.gitignore create mode 100644 counter/README.md create mode 100644 counter/foundry.toml create mode 160000 counter/lib/forge-std create mode 160000 counter/lib/openzeppelin-contracts create mode 100644 counter/script/Counter.s.sol create mode 100644 counter/src/Counter.sol create mode 100644 counter/test/Counter.t.sol diff --git a/.codesandbox/tasks.json b/.codesandbox/tasks.json new file mode 100644 index 0000000000000..b34104d5de54e --- /dev/null +++ b/.codesandbox/tasks.json @@ -0,0 +1,7 @@ +{ + // These tasks will run in order when initializing your CodeSandbox project. + "setupTasks": [], + + // These tasks can be run from CodeSandbox. Running one will open a log in the app. + "tasks": {} +} diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000000..b1269653d9c6f --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "counter/lib/forge-std"] + path = counter/lib/forge-std + url = https://github.com/foundry-rs/forge-std +[submodule "counter/lib/openzeppelin-contracts"] + path = counter/lib/openzeppelin-contracts + url = https://github.com/OpenZeppelin/openzeppelin-contracts diff --git a/counter/.github/workflows/test.yml b/counter/.github/workflows/test.yml new file mode 100644 index 0000000000000..34a4a527be6f9 --- /dev/null +++ b/counter/.github/workflows/test.yml @@ -0,0 +1,43 @@ +name: CI + +on: + push: + pull_request: + workflow_dispatch: + +env: + FOUNDRY_PROFILE: ci + +jobs: + check: + strategy: + fail-fast: true + + name: Foundry project + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + + - name: Show Forge version + run: | + forge --version + + - name: Run Forge fmt + run: | + forge fmt --check + id: fmt + + - name: Run Forge build + run: | + forge build --sizes + id: build + + - name: Run Forge tests + run: | + forge test -vvv + id: test diff --git a/counter/.gitignore b/counter/.gitignore new file mode 100644 index 0000000000000..85198aaa55b84 --- /dev/null +++ b/counter/.gitignore @@ -0,0 +1,14 @@ +# Compiler files +cache/ +out/ + +# Ignores development broadcast logs +!/broadcast +/broadcast/*/31337/ +/broadcast/**/dry-run/ + +# Docs +docs/ + +# Dotenv file +.env diff --git a/counter/README.md b/counter/README.md new file mode 100644 index 0000000000000..9265b4558406a --- /dev/null +++ b/counter/README.md @@ -0,0 +1,66 @@ +## Foundry + +**Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.** + +Foundry consists of: + +- **Forge**: Ethereum testing framework (like Truffle, Hardhat and DappTools). +- **Cast**: Swiss army knife for interacting with EVM smart contracts, sending transactions and getting chain data. +- **Anvil**: Local Ethereum node, akin to Ganache, Hardhat Network. +- **Chisel**: Fast, utilitarian, and verbose solidity REPL. + +## Documentation + +https://book.getfoundry.sh/ + +## Usage + +### Build + +```shell +$ forge build +``` + +### Test + +```shell +$ forge test +``` + +### Format + +```shell +$ forge fmt +``` + +### Gas Snapshots + +```shell +$ forge snapshot +``` + +### Anvil + +```shell +$ anvil +``` + +### Deploy + +```shell +$ forge script script/Counter.s.sol:CounterScript --rpc-url --private-key +``` + +### Cast + +```shell +$ cast +``` + +### Help + +```shell +$ forge --help +$ anvil --help +$ cast --help +``` diff --git a/counter/foundry.toml b/counter/foundry.toml new file mode 100644 index 0000000000000..25b918f9c9a96 --- /dev/null +++ b/counter/foundry.toml @@ -0,0 +1,6 @@ +[profile.default] +src = "src" +out = "out" +libs = ["lib"] + +# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options diff --git a/counter/lib/forge-std b/counter/lib/forge-std new file mode 160000 index 0000000000000..3b20d60d14b34 --- /dev/null +++ b/counter/lib/forge-std @@ -0,0 +1 @@ +Subproject commit 3b20d60d14b343ee4f908cb8079495c07f5e8981 diff --git a/counter/lib/openzeppelin-contracts b/counter/lib/openzeppelin-contracts new file mode 160000 index 0000000000000..acd4ff74de833 --- /dev/null +++ b/counter/lib/openzeppelin-contracts @@ -0,0 +1 @@ +Subproject commit acd4ff74de833399287ed6b31b4debf6b2b35527 diff --git a/counter/script/Counter.s.sol b/counter/script/Counter.s.sol new file mode 100644 index 0000000000000..cdc1fe9a1ba25 --- /dev/null +++ b/counter/script/Counter.s.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +import {Script, console} from "forge-std/Script.sol"; +import {Counter} from "../src/Counter.sol"; + +contract CounterScript is Script { + Counter public counter; + + function setUp() public {} + + function run() public { + vm.startBroadcast(); + + counter = new Counter(); + + vm.stopBroadcast(); + } +} diff --git a/counter/src/Counter.sol b/counter/src/Counter.sol new file mode 100644 index 0000000000000..aded7997b0c35 --- /dev/null +++ b/counter/src/Counter.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +contract Counter { + uint256 public number; + + function setNumber(uint256 newNumber) public { + number = newNumber; + } + + function increment() public { + number++; + } +} diff --git a/counter/test/Counter.t.sol b/counter/test/Counter.t.sol new file mode 100644 index 0000000000000..54b724f7ae766 --- /dev/null +++ b/counter/test/Counter.t.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +import {Test, console} from "forge-std/Test.sol"; +import {Counter} from "../src/Counter.sol"; + +contract CounterTest is Test { + Counter public counter; + + function setUp() public { + counter = new Counter(); + counter.setNumber(0); + } + + function test_Increment() public { + counter.increment(); + assertEq(counter.number(), 1); + } + + function testFuzz_SetNumber(uint256 x) public { + counter.setNumber(x); + assertEq(counter.number(), x); + } +} From fdfd0e77852f21551fee8185091a2ba3be6dcb30 Mon Sep 17 00:00:00 2001 From: Legion's <64915515+Dargon789@users.noreply.github.com> Date: Wed, 5 Mar 2025 22:11:02 +0000 Subject: [PATCH 015/232] diff sig --- counter/lib/openzeppelin-contracts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/counter/lib/openzeppelin-contracts b/counter/lib/openzeppelin-contracts index acd4ff74de833..4458d32fb643a 160000 --- a/counter/lib/openzeppelin-contracts +++ b/counter/lib/openzeppelin-contracts @@ -1 +1 @@ -Subproject commit acd4ff74de833399287ed6b31b4debf6b2b35527 +Subproject commit 4458d32fb643a22ac81698c5ce3ca3ca9fed5a50 From a0a8bde78ec08ddd85eafe773cde166203b0cf83 Mon Sep 17 00:00:00 2001 From: samooyo Date: Thu, 6 Mar 2025 14:14:51 +0100 Subject: [PATCH 016/232] feat(forge): add params natspec for enums --- crates/doc/src/parser/comment.rs | 12 +++++-- crates/doc/src/writer/as_doc.rs | 11 ++++++- crates/doc/src/writer/buf_writer.rs | 51 +++++++++++++++++++++++++++-- 3 files changed, 68 insertions(+), 6 deletions(-) diff --git a/crates/doc/src/parser/comment.rs b/crates/doc/src/parser/comment.rs index bf2b0ad7b4f0d..cba7f32df2767 100644 --- a/crates/doc/src/parser/comment.rs +++ b/crates/doc/src/parser/comment.rs @@ -46,7 +46,7 @@ impl CommentTag { } _ => { warn!(target: "forge::doc", tag=trimmed, "unknown comment tag. custom tags must be preceded by `custom:`"); - return None + return None; } }; Some(tag) @@ -157,6 +157,12 @@ impl From> for Comments { } } +impl From> for Comments { + fn from(value: Vec) -> Self { + Self(value) + } +} + /// The collection of references to natspec [Comment] items. #[derive(Debug, Default, PartialEq, Deref)] pub struct CommentsRef<'a>(Vec<&'a Comment>); @@ -184,8 +190,8 @@ impl<'a> CommentsRef<'a> { self.iter().any(|c| match (&c.tag, &target.tag) { (CommentTag::Inheritdoc, CommentTag::Inheritdoc) => c.value == target.value, (CommentTag::Param, CommentTag::Param) | (CommentTag::Return, CommentTag::Return) => { - c.split_first_word().map(|(name, _)| name) == - target.split_first_word().map(|(name, _)| name) + c.split_first_word().map(|(name, _)| name) + == target.split_first_word().map(|(name, _)| name) } (tag1, tag2) => tag1 == tag2, }) diff --git a/crates/doc/src/writer/as_doc.rs b/crates/doc/src/writer/as_doc.rs index 56a0a4026c504..98fe8f668eca0 100644 --- a/crates/doc/src/writer/as_doc.rs +++ b/crates/doc/src/writer/as_doc.rs @@ -229,7 +229,16 @@ impl AsDoc for Document { writer.write_subtitle("Enums")?; enums.into_iter().try_for_each(|(item, comments, code)| { writer.write_heading(&item.name.safe_unwrap().name)?; - writer.write_section(comments, code) + + let filtered_comments: Comments = (*comments) + .iter() + .cloned() + .filter(|c| c.tag != CommentTag::Custom("variant".to_string())) + .collect::>() + .into(); + + writer.write_section(&filtered_comments, code)?; + writer.try_write_variant_table(&item, comments) })?; } } diff --git a/crates/doc/src/writer/buf_writer.rs b/crates/doc/src/writer/buf_writer.rs index e6109c338c03f..152f29dc61345 100644 --- a/crates/doc/src/writer/buf_writer.rs +++ b/crates/doc/src/writer/buf_writer.rs @@ -1,6 +1,8 @@ use crate::{writer::traits::ParamLike, AsDoc, CommentTag, Comments, Deployment, Markdown}; use itertools::Itertools; -use solang_parser::pt::{ErrorParameter, EventParameter, Parameter, VariableDeclaration}; +use solang_parser::pt::{ + EnumDefinition, ErrorParameter, EventParameter, Parameter, VariableDeclaration, +}; use std::{ fmt::{self, Display, Write}, sync::LazyLock, @@ -19,6 +21,11 @@ const DEPLOYMENTS_TABLE_HEADERS: &[&str] = &["Network", "Address"]; static DEPLOYMENTS_TABLE_SEPARATOR: LazyLock = LazyLock::new(|| DEPLOYMENTS_TABLE_HEADERS.iter().map(|h| "-".repeat(h.len())).join("|")); +/// Headers and separator for rendering the variants table. +const VARIANTS_TABLE_HEADERS: &[&str] = &["Name", "Description"]; +const VARIANTS_TABLE_SEPARATOR: LazyLock = + LazyLock::new(|| VARIANTS_TABLE_HEADERS.iter().map(|h| "-".repeat(h.len())).join("|")); + /// The buffered writer. /// Writes various display items into the internal buffer. #[derive(Debug, Default)] @@ -132,7 +139,7 @@ impl BufWriter { // There is nothing to write. if params.is_empty() || comments.is_empty() { - return Ok(()) + return Ok(()); } self.write_bold(heading)?; @@ -177,6 +184,46 @@ impl BufWriter { self.try_write_table(CommentTag::Param, params, comments, "Properties") } + /// Tries to write the variant table to the buffer. + /// Doesn't write anything if either params or comments are empty. + pub fn try_write_variant_table( + &mut self, + params: &EnumDefinition, + comments: &Comments, + ) -> fmt::Result { + let comments = + comments.include_tags(&[CommentTag::Param, CommentTag::Custom("variant".to_string())]); + + // There is nothing to write. + if comments.is_empty() { + return Ok(()); + } + + self.write_bold("Variants")?; + self.writeln()?; + + self.write_piped(&VARIANTS_TABLE_HEADERS.join("|"))?; + self.write_piped(&VARIANTS_TABLE_SEPARATOR)?; + + for value in params.values.iter() { + let param_name = value.as_ref().map(|v| v.name.clone()); + + let comment = param_name.as_ref().and_then(|name| { + comments.iter().find_map(|comment| comment.match_first_word(name)) + }); + + let row = [ + Markdown::Code(¶m_name.unwrap_or("".to_string())).as_doc()?, + comment.unwrap_or_default().replace('\n', " "), + ]; + self.write_piped(&row.join("|"))?; + } + + self.writeln()?; + + Ok(()) + } + /// Tries to write the parameters table to the buffer. /// Doesn't write anything if either params or comments are empty. pub fn try_write_events_table( From c0b572530bad0202ee38f95f05988273b6ffda02 Mon Sep 17 00:00:00 2001 From: samooyo Date: Thu, 6 Mar 2025 14:15:45 +0100 Subject: [PATCH 017/232] chore: cargo fmt --- crates/doc/src/parser/comment.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/doc/src/parser/comment.rs b/crates/doc/src/parser/comment.rs index cba7f32df2767..5dc6c17f98890 100644 --- a/crates/doc/src/parser/comment.rs +++ b/crates/doc/src/parser/comment.rs @@ -190,8 +190,8 @@ impl<'a> CommentsRef<'a> { self.iter().any(|c| match (&c.tag, &target.tag) { (CommentTag::Inheritdoc, CommentTag::Inheritdoc) => c.value == target.value, (CommentTag::Param, CommentTag::Param) | (CommentTag::Return, CommentTag::Return) => { - c.split_first_word().map(|(name, _)| name) - == target.split_first_word().map(|(name, _)| name) + c.split_first_word().map(|(name, _)| name) == + target.split_first_word().map(|(name, _)| name) } (tag1, tag2) => tag1 == tag2, }) From d6033484b6f75de82b51eec87e1d0f36745898ac Mon Sep 17 00:00:00 2001 From: samooyo Date: Thu, 6 Mar 2025 14:23:16 +0100 Subject: [PATCH 018/232] fix: clippy errors --- crates/doc/src/writer/as_doc.rs | 4 ++-- crates/doc/src/writer/buf_writer.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/doc/src/writer/as_doc.rs b/crates/doc/src/writer/as_doc.rs index 98fe8f668eca0..d38f880ed8693 100644 --- a/crates/doc/src/writer/as_doc.rs +++ b/crates/doc/src/writer/as_doc.rs @@ -232,13 +232,13 @@ impl AsDoc for Document { let filtered_comments: Comments = (*comments) .iter() - .cloned() .filter(|c| c.tag != CommentTag::Custom("variant".to_string())) + .cloned() .collect::>() .into(); writer.write_section(&filtered_comments, code)?; - writer.try_write_variant_table(&item, comments) + writer.try_write_variant_table(item, comments) })?; } } diff --git a/crates/doc/src/writer/buf_writer.rs b/crates/doc/src/writer/buf_writer.rs index 152f29dc61345..7fb657ba1d7a4 100644 --- a/crates/doc/src/writer/buf_writer.rs +++ b/crates/doc/src/writer/buf_writer.rs @@ -23,7 +23,7 @@ static DEPLOYMENTS_TABLE_SEPARATOR: LazyLock = /// Headers and separator for rendering the variants table. const VARIANTS_TABLE_HEADERS: &[&str] = &["Name", "Description"]; -const VARIANTS_TABLE_SEPARATOR: LazyLock = +static VARIANTS_TABLE_SEPARATOR: LazyLock = LazyLock::new(|| VARIANTS_TABLE_HEADERS.iter().map(|h| "-".repeat(h.len())).join("|")); /// The buffered writer. From 4cae0e34a3da13bbd8f6f4ce5236624b8f59d11d Mon Sep 17 00:00:00 2001 From: zerosnacks Date: Fri, 7 Mar 2025 16:33:09 +0100 Subject: [PATCH 019/232] add @gregorsternat as co-author given their earlier work on https://github.com/foundry-rs/foundry/pull/9905 Co-authored-by: gregorsternat From ffefcd22688e53b429034b088442c51427c140c6 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Sat, 8 Mar 2025 20:05:26 +0700 Subject: [PATCH 020/232] Update openzeppelin-contracts --- counter/lib/openzeppelin-contracts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/counter/lib/openzeppelin-contracts b/counter/lib/openzeppelin-contracts index 4458d32fb643a..ca7a4e39de086 160000 --- a/counter/lib/openzeppelin-contracts +++ b/counter/lib/openzeppelin-contracts @@ -1 +1 @@ -Subproject commit 4458d32fb643a22ac81698c5ce3ca3ca9fed5a50 +Subproject commit ca7a4e39de0860bbaadf95824207886e6de9fa64 From 30ccc2c75b877cfcbae31435d42bb8d0ff616be7 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Sun, 9 Mar 2025 18:58:29 +0700 Subject: [PATCH 021/232] chore(deps): weekly `cargo update` (#10039) (#22) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- Cargo.lock | 160 +++++++++++++++++++++++++---------------------------- 1 file changed, 76 insertions(+), 84 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3fc0e255c012d..1cea57209a9b5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -86,9 +86,9 @@ dependencies = [ [[package]] name = "alloy-consensus" -version = "0.12.1" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffc96bae4737f5a8c8fae0db8fe9f000ebf3dd9894db755ba178fedbbab244d6" +checksum = "1715ed2a977d3ca4b39ffe0fc69f9f5b0e81382b348bdb5172abaa77a10f0b6d" dependencies = [ "alloy-eips", "alloy-primitives", @@ -109,9 +109,9 @@ dependencies = [ [[package]] name = "alloy-consensus-any" -version = "0.12.0" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f02faf3f83ddd877925a46bc206eb70f718e0c438b3159cd153751cde7ade7a" +checksum = "660705969af143897d83937d73f53c741c1587f49c27c2cfce594e188fcbc1e4" dependencies = [ "alloy-consensus", "alloy-eips", @@ -123,9 +123,9 @@ dependencies = [ [[package]] name = "alloy-contract" -version = "0.12.1" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e47250b3cd43cf7a89aab508a81c11a1b92acd7f13b2200df21aed83cc3e1da7" +checksum = "5362637b25ba5282a921ca139a10f188fa34e1248a7c83c907a21de54d36dce1" dependencies = [ "alloy-dyn-abi", "alloy-json-abi", @@ -206,9 +206,9 @@ dependencies = [ [[package]] name = "alloy-eips" -version = "0.12.1" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b48f915ccad936effcfb6f3711225f3e00e1db0effd6faf7da57518da325c88" +checksum = "d13734f722326c846e7690ce732c9864f5ae82f52c7fb60c871f56654f348d4c" dependencies = [ "alloy-eip2124", "alloy-eip2930", @@ -227,9 +227,9 @@ dependencies = [ [[package]] name = "alloy-genesis" -version = "0.12.1" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78f88ea3da00e9f890ea8c6913dba52025454c34a57df893dab1d7b0e3c53615" +checksum = "738b6d7da21955cfdebeb7bcf300040b79e51c58a22e5f029ae989a8d834a3f3" dependencies = [ "alloy-eips", "alloy-primitives", @@ -252,9 +252,9 @@ dependencies = [ [[package]] name = "alloy-json-rpc" -version = "0.12.1" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aba0e8a8d1bf498da62affe8472e1ee2fd064144d5826a1088a49416f2f448a3" +checksum = "e6fbb61c4dfe5def9a065438162faf39503b3e8d90f36d01563418a75f0ef016" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -266,9 +266,9 @@ dependencies = [ [[package]] name = "alloy-network" -version = "0.12.1" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64fc810a9967c3a6c69f9e9b2bb68bb13bd919aa741a533bdd5bf074f4a6709b" +checksum = "f10b0bc0657b018ee4f3758f889d066af6b1f20f57cd825b540182029090c151" dependencies = [ "alloy-consensus", "alloy-consensus-any", @@ -292,9 +292,9 @@ dependencies = [ [[package]] name = "alloy-network-primitives" -version = "0.12.0" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3dddaef8fc70307e8775be36a853e6118a628842d013f77f2c73ee48497aaf6" +checksum = "6cac4aeeabbbc16623d0745ae3b5a515d727ce8ef4ec4b6a886c3634d8b298fe" dependencies = [ "alloy-consensus", "alloy-eips", @@ -305,9 +305,9 @@ dependencies = [ [[package]] name = "alloy-node-bindings" -version = "0.12.1" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2fc757d22ea387b404036301201e54f24e2f4f6a9632b6d8bd58d06d0abfa3b" +checksum = "d9151507742ac142201c3a56f74fd94c2ceda96115eed60a3dabaeef85e6b64a" dependencies = [ "alloy-genesis", "alloy-network", @@ -356,9 +356,9 @@ dependencies = [ [[package]] name = "alloy-provider" -version = "0.12.1" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57dc6935c8b91fc742c6f2b6f100ea04060475b312c245b42a63729f4299951f" +checksum = "d06ffafc44e68c8244feb51919895c679c153a0b143c182e1ffe8cce998abf15" dependencies = [ "alloy-chains", "alloy-consensus", @@ -399,9 +399,9 @@ dependencies = [ [[package]] name = "alloy-pubsub" -version = "0.12.1" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e7538324684444a59fde89469f2dc097bca7dc2ee024e214f3a48c21917978f" +checksum = "6abe9f9e6be75dc8532bb2bf3f4c700c9e7bce8a3b05ec702a7324abdb118016" dependencies = [ "alloy-json-rpc", "alloy-primitives", @@ -440,9 +440,9 @@ dependencies = [ [[package]] name = "alloy-rpc-client" -version = "0.12.1" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7604f6c3438bf48d5d183fa9dd02a0a0151a631eb15c1444ea4630c7f75b4271" +checksum = "c9ae316fdb92a4546f0dba4919ea4c1c0edb89a876536520c248fada0febac5d" dependencies = [ "alloy-json-rpc", "alloy-primitives", @@ -466,9 +466,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types" -version = "0.12.1" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0957527935118dfb52427d220f326a80f6b99e9d21b94fa16d884d150ddc814" +checksum = "61e50cc5a693dfbef452e3dbcea3cd3342840d10eb3ffa018b0a5676967d8b6b" dependencies = [ "alloy-primitives", "alloy-rpc-types-anvil", @@ -482,9 +482,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-anvil" -version = "0.12.0" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b94cd833d43007286d1a3ff1246a8cd8f1d9a5854248e766e29f84b7d8a5bb86" +checksum = "2852d7350760c3fbfc60ee3396b95a66ea57afe3aeecee72bf1171ac6b1d5d18" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", @@ -494,9 +494,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-any" -version = "0.12.0" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a84ae770c31d4aae0ce056ff594dffc8bb51cc246d1854ddae5083fbd978ef58" +checksum = "f726ebb03d5918a946d0a6e17829cabd90ffe928664dc3f7fdbba1be511760de" dependencies = [ "alloy-consensus-any", "alloy-rpc-types-eth", @@ -505,9 +505,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-debug" -version = "0.12.0" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ed0352a0e8c55f6a53e82509342b5c3ff6a449601cb393569ce597d09ee816d" +checksum = "ab1fe2c636a14190fe3c6caf6a20d2fb8691a5824c1789ee495324a14295df82" dependencies = [ "alloy-primitives", "serde", @@ -515,9 +515,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-engine" -version = "0.12.0" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29d5c16b174beb31b50cbfc754b879dc9473bce12d0f2c4675d79419ed7381f5" +checksum = "b05bfe640e4708c5a83dfcc65b5e4a0deb6ddcb18897dd49862ddc3964e06ff8" dependencies = [ "alloy-consensus", "alloy-eips", @@ -533,9 +533,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-eth" -version = "0.12.0" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "171bf00513b8cbfb338a9028f9151cac787c2fca5fc923c2c2201b059444df44" +checksum = "c24a3b6c552b74c4abdbaa45fd467a230f5564f62c6adae16972dd90b6b4dca5" dependencies = [ "alloy-consensus", "alloy-consensus-any", @@ -553,9 +553,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-trace" -version = "0.12.0" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658eb579d6499139da033c0b7e5a302dad90bb57c4e722250dd82636de035936" +checksum = "e25f16f6bfe65c23d873741aa343830de270db42c982822e23689d11f2f4d812" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", @@ -567,9 +567,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-txpool" -version = "0.12.0" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51305494072ed029790cdfe322a1a30d7d8a0baf47ad8f61b5981354e298741" +checksum = "9415e7e3f32a93a38ecb83aa449f7326081b5b362964291463f8f2060b4b8a31" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", @@ -579,9 +579,9 @@ dependencies = [ [[package]] name = "alloy-serde" -version = "0.12.1" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de933b08fd186491d7171b4075c54ccf37d3f4fe17178bc3a8ba7cd1e77fb387" +checksum = "3aebca035ca670bd7de8165a9494c0d502625e26129dd95d17fdfd70d5521c02" dependencies = [ "alloy-primitives", "serde", @@ -590,9 +590,9 @@ dependencies = [ [[package]] name = "alloy-signer" -version = "0.12.1" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b55818175303de00576c5eb27ffa22ca31efe481e81cac7b05cc87e5f0ba2153" +checksum = "7abfef2a155c7d6a9f54861159a3fdd29abe1f67f0865b081bce4c2fdc9e83cc" dependencies = [ "alloy-dyn-abi", "alloy-primitives", @@ -607,9 +607,9 @@ dependencies = [ [[package]] name = "alloy-signer-aws" -version = "0.12.1" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57980f25e09e42aaa0eb9267951f54de06a59f66b8b12c74d47b2128a4456a5b" +checksum = "f25d4994d79911d1fdf64945c8fc08df46e0ba828abd5c7505264b7012318443" dependencies = [ "alloy-consensus", "alloy-network", @@ -625,9 +625,9 @@ dependencies = [ [[package]] name = "alloy-signer-gcp" -version = "0.12.1" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3369ce741e4c0cbdb44db9761f5767befc03b8c63f469c57a821d101197d65fc" +checksum = "4316e51a4131884e42a5d8b3228a508a60d280add3742bc1196b81f758b7c204" dependencies = [ "alloy-consensus", "alloy-network", @@ -643,9 +643,9 @@ dependencies = [ [[package]] name = "alloy-signer-ledger" -version = "0.12.1" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54fef49330880f268f3cab430f3d69665436b2e651dd9ba2cbfdd1cef3100d8e" +checksum = "4097dcfbbef9ca5bc3c02901af815c82db89a1a429520acad1c34a0b136acbba" dependencies = [ "alloy-consensus", "alloy-dyn-abi", @@ -663,9 +663,9 @@ dependencies = [ [[package]] name = "alloy-signer-local" -version = "0.12.1" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1b1094d0e467f8bea128fc7a4d853a1300c53d20c9b2fddd76d59cc3b25d787" +checksum = "326033310c939b0d00b03fdbe2c243cb45add25c4e195d97b1792883c93a4c4c" dependencies = [ "alloy-consensus", "alloy-network", @@ -682,9 +682,9 @@ dependencies = [ [[package]] name = "alloy-signer-trezor" -version = "0.12.1" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0586b1a20d7559d21f7e33318fa5881bf850f94c58b37e74a5ba245c34d8b80c" +checksum = "c6da910dc4386ab642a58a5a98cec80ecb47855b28b340a997ba7fa019f1cec0" dependencies = [ "alloy-consensus", "alloy-network", @@ -772,9 +772,9 @@ dependencies = [ [[package]] name = "alloy-transport" -version = "0.12.1" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9f400ac2a4da066cd5c8beb4efc6b97111ac43e205928534768671b6cf2b7b" +checksum = "463f6cb5234c7420e7e77c248c0460a8e2dea933f2bb4e8f169d5f12510b38e0" dependencies = [ "alloy-json-rpc", "base64 0.22.1", @@ -791,9 +791,9 @@ dependencies = [ [[package]] name = "alloy-transport-http" -version = "0.12.1" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b582d46a163af722ce965e014933c19994c5161979929ce1e486067cf4503a0" +checksum = "1eacd1c195c2a706bfbc92113d4bd3481b0dbd1742923a232dbe8a7910ac0fe5" dependencies = [ "alloy-json-rpc", "alloy-transport", @@ -806,9 +806,9 @@ dependencies = [ [[package]] name = "alloy-transport-ipc" -version = "0.12.1" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6c7b142bd57d2416453c762c6216315562f1b9ed5db2019539d5b34032f655f" +checksum = "6c5d3531e65eed82f14f93bb668fb06797c3754d0141c5da042bb63c5c19f13c" dependencies = [ "alloy-json-rpc", "alloy-pubsub", @@ -827,9 +827,9 @@ dependencies = [ [[package]] name = "alloy-transport-ws" -version = "0.12.1" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c2dec526ed36192bfb9f02e6b7e4575a5135c358a96d786bfb42d691a3ca898" +checksum = "218e64c375edd8fe8d00d9aa983fb2d85f7cfeebb91f707fe4c7ba52410803f5" dependencies = [ "alloy-pubsub", "alloy-transport", @@ -2606,12 +2606,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "critical-section" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" - [[package]] name = "crossbeam-channel" version = "0.5.14" @@ -5463,9 +5457,9 @@ dependencies = [ [[package]] name = "interprocess" -version = "2.2.2" +version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "894148491d817cb36b6f778017b8ac46b17408d522dd90f539d677ea938362eb" +checksum = "d941b405bd2322993887859a8ee6ac9134945a24ec5ec763a8a962fc64dfec2d" dependencies = [ "doctest-file", "futures-core", @@ -5884,9 +5878,9 @@ dependencies = [ [[package]] name = "mdbook" -version = "0.4.45" +version = "0.4.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b07d36d96ffe1b5b16ddf2bc80b3b26bb7a498b2a6591061250bf0af8e8095ad" +checksum = "85c54109598152e19add1933b223b1913bcd16e27cbd7c2783269fe2f9a6cbdc" dependencies = [ "ammonia", "anyhow", @@ -5896,6 +5890,7 @@ dependencies = [ "elasticlunr-rs", "env_logger", "handlebars", + "hex", "log", "memchr", "once_cell", @@ -5904,6 +5899,7 @@ dependencies = [ "regex", "serde", "serde_json", + "sha2", "shlex", "tempfile", "toml 0.5.11", @@ -6344,10 +6340,6 @@ name = "once_cell" version = "1.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" -dependencies = [ - "critical-section", - "portable-atomic", -] [[package]] name = "op-alloy-consensus" @@ -7681,9 +7673,9 @@ dependencies = [ [[package]] name = "rustix" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17f8dcd64f141950290e45c99f7710ede1b600297c91818bb30b3667c0f45dc0" +checksum = "dade4812df5c384711475be5fcd8c162555352945401aed22a35bffeab61f657" dependencies = [ "bitflags 2.9.0", "errno", @@ -8840,7 +8832,7 @@ dependencies = [ "fastrand", "getrandom 0.3.1", "once_cell", - "rustix 1.0.0", + "rustix 1.0.1", "windows-sys 0.59.0", ] @@ -8868,11 +8860,11 @@ dependencies = [ [[package]] name = "terminal_size" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5352447f921fda68cf61b4101566c0bdb5104eff6804d0678e5227580ab6a4e9" +checksum = "45c6481c4829e4cc63825e62c49186a34538b7b2750b73b266581ffb612fb5ed" dependencies = [ - "rustix 0.38.44", + "rustix 1.0.1", "windows-sys 0.59.0", ] @@ -9053,9 +9045,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.43.0" +version = "1.44.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" +checksum = "9975ea0f48b5aa3972bf2d888c238182458437cc2a19374b81b25cdf1023fb3a" dependencies = [ "backtrace", "bytes", From c235592917161f2eba6ec443739e84e524de9174 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Wed, 12 Mar 2025 02:59:45 +0700 Subject: [PATCH 022/232] python3-compile-vyper-contract (#27) * fix deny.toml, ignore RUSTSEC-2025-0014 (#10052) * fix deny.toml, ignore RUSTSEC-2025-0014 * roll back allow-git * update derive_more to 2.0 (#9987) * chore: fix ci, bump python setup version (#10054) Bump gh python setup version * feat(forge): match chain id with token symbol (#10043) * feat: match chain id with token symbol * fix: change symbol from matic to pol * fix: use NameChain instead of manual mapping * Fix tests, fmt and clippy --------- Co-authored-by: grandizzy <38490174+grandizzy@users.noreply.github.com> Co-authored-by: grandizzy * feat(cast): storage add --proxy to manually specify a proxy contract when Etherscan fails to find it (#10033) * Adding a proxy parameter to the cast storage command, allowing manual selection of a proxy address to retrieve the full storage layout. * Adding tests for the cast storage proxy optional argument. * Using if let some else pattern. * Improved documentation. --------- Co-authored-by: grandizzy <38490174+grandizzy@users.noreply.github.com> * fix(forge): use etherscan verifier if key provided (#10058) * fix(forge): use etherscan if key provided * Changes after review: expose is_sourcify and is_etherscan fns --------- Co-authored-by: gerald <3949379+getong@users.noreply.github.com> Co-authored-by: grandizzy <38490174+grandizzy@users.noreply.github.com> Co-authored-by: supamongkonR <73258014+supamongkonR@users.noreply.github.com> Co-authored-by: grandizzy Co-authored-by: Cizeon <110527347+Cizeon@users.noreply.github.com> --- .github/workflows/nextest.yml | 4 +- Cargo.lock | 347 +++++++++++++++++------------ Cargo.toml | 2 +- crates/cast/bin/cmd/storage.rs | 10 +- crates/cast/tests/cli/main.rs | 42 ++++ crates/forge/tests/cli/script.rs | 2 +- crates/script/src/simulate.rs | 10 +- crates/test-utils/src/util.rs | 5 +- crates/verify/src/etherscan/mod.rs | 9 +- crates/verify/src/provider.rs | 19 +- deny.toml | 3 +- 11 files changed, 295 insertions(+), 158 deletions(-) diff --git a/.github/workflows/nextest.yml b/.github/workflows/nextest.yml index c8c0e0961eb0c..5f8a9561af7d4 100644 --- a/.github/workflows/nextest.yml +++ b/.github/workflows/nextest.yml @@ -68,11 +68,11 @@ jobs: with: bun-version: latest - name: Setup Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: 3.11 - name: Install Vyper - run: pip install vyper==0.4.0 + run: pip --version && pip install vyper==0.4.0 - name: Forge RPC cache uses: actions/cache@v3 diff --git a/Cargo.lock b/Cargo.lock index aed90b9330cf4..f02aec99ed670 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -339,7 +339,7 @@ dependencies = [ "foldhash", "getrandom 0.2.15", "hashbrown 0.15.2", - "indexmap 2.7.1", + "indexmap 2.8.0", "itoa", "k256", "keccak-asm", @@ -435,7 +435,7 @@ checksum = "a40e1ef334153322fd878d07e86af7a529bcb86b2439525920a88eba87bcf943" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -708,7 +708,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -721,11 +721,11 @@ dependencies = [ "alloy-sol-macro-input", "const-hex", "heck", - "indexmap 2.7.1", + "indexmap 2.8.0", "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", "syn-solidity", "tiny-keccak", ] @@ -743,7 +743,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.99", + "syn 2.0.100", "syn-solidity", ] @@ -1289,7 +1289,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -1311,7 +1311,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -1322,7 +1322,7 @@ checksum = "d556ec1359574147ec0c4fc5eb525f3f23263a592b1a9c07e0a75b427de55c97" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -1375,7 +1375,7 @@ checksum = "e12882f59de5360c748c4cbf569a042d5fb0eb515f7bea9c1f470b47f6ffbd73" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -1565,9 +1565,9 @@ dependencies = [ [[package]] name = "aws-smithy-async" -version = "1.2.4" +version = "1.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa59d1327d8b5053c54bf2eaae63bf629ba9e904434d0835a28ed3c0ed0a614e" +checksum = "1e190749ea56f8c42bf15dd76c65e14f8f765233e6df9b0506d9d934ebef867c" dependencies = [ "futures-util", "pin-project-lite", @@ -1614,11 +1614,52 @@ dependencies = [ "tracing", ] +[[package]] +name = "aws-smithy-http" +version = "0.62.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5949124d11e538ca21142d1fba61ab0a2a2c1bc3ed323cdb3e4b878bfb83166" +dependencies = [ + "aws-smithy-runtime-api", + "aws-smithy-types", + "bytes", + "bytes-utils", + "futures-core", + "http 0.2.12", + "http 1.2.0", + "http-body 0.4.6", + "once_cell", + "percent-encoding", + "pin-project-lite", + "pin-utils", + "tracing", +] + +[[package]] +name = "aws-smithy-http-client" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0497ef5d53065b7cd6a35e9c1654bd1fefeae5c52900d91d1b188b0af0f29324" +dependencies = [ + "aws-smithy-async", + "aws-smithy-runtime-api", + "aws-smithy-types", + "h2 0.4.8", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.32", + "hyper-rustls 0.24.2", + "pin-project-lite", + "rustls 0.21.12", + "tokio", + "tracing", +] + [[package]] name = "aws-smithy-json" -version = "0.61.2" +version = "0.61.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "623a51127f24c30776c8b374295f2df78d92517386f77ba30773f15a30ce1422" +checksum = "92144e45819cae7dc62af23eac5a038a58aa544432d2102609654376a900bd07" dependencies = [ "aws-smithy-types", ] @@ -1635,36 +1676,33 @@ dependencies = [ [[package]] name = "aws-smithy-runtime" -version = "1.7.8" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d526a12d9ed61fadefda24abe2e682892ba288c2018bcb38b1b4c111d13f6d92" +checksum = "f6328865e36c6fd970094ead6b05efd047d3a80ec5fc3be5e743910da9f2ebf8" dependencies = [ "aws-smithy-async", - "aws-smithy-http 0.60.12", + "aws-smithy-http 0.62.0", + "aws-smithy-http-client", "aws-smithy-runtime-api", "aws-smithy-types", "bytes", "fastrand", - "h2 0.3.26", "http 0.2.12", + "http 1.2.0", "http-body 0.4.6", "http-body 1.0.1", - "httparse", - "hyper 0.14.32", - "hyper-rustls 0.24.2", "once_cell", "pin-project-lite", "pin-utils", - "rustls 0.21.12", "tokio", "tracing", ] [[package]] name = "aws-smithy-runtime-api" -version = "1.7.3" +version = "1.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92165296a47a812b267b4f41032ff8069ab7ff783696d217f0994a0d7ab585cd" +checksum = "3da37cf5d57011cb1753456518ec76e31691f1f474b73934a284eb2a1c76510f" dependencies = [ "aws-smithy-async", "aws-smithy-types", @@ -1679,9 +1717,9 @@ dependencies = [ [[package]] name = "aws-smithy-types" -version = "1.2.13" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7b8a53819e42f10d0821f56da995e1470b199686a1809168db6ca485665f042" +checksum = "836155caafba616c0ff9b07944324785de2ab016141c3550bd1c07882f8cee8f" dependencies = [ "base64-simd", "bytes", @@ -1826,9 +1864,9 @@ dependencies = [ [[package]] name = "base64ct" -version = "1.6.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +checksum = "bb97d56060ee67d285efb8001fec9d2a4c710c32efd2e14b5cbb5ba71930fc2d" [[package]] name = "bech32" @@ -1944,7 +1982,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -2233,9 +2271,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.31" +version = "4.5.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "027bb0d98429ae334a8698531da7077bdf906419543a35a55c2cb1b66437d767" +checksum = "6088f3ae8c3608d19260cd7445411865a485688711b78b5be70d78cd96136f83" dependencies = [ "clap_builder", "clap_derive", @@ -2243,9 +2281,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.31" +version = "4.5.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5589e0cba072e0f3d23791efac0fd8627b49c829c196a492e88168e6a669d863" +checksum = "22a7ef7f676155edfb82daa97f99441f3ebf4a58d5e32f295a56259f1b6facc8" dependencies = [ "anstream", "anstyle", @@ -2277,14 +2315,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.28" +version = "4.5.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4ced95c6f4a675af3da73304b9ac4ed991640c36374e4b46795c49e17cf1ed" +checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -2540,9 +2578,9 @@ dependencies = [ [[package]] name = "convert_case" -version = "0.6.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +checksum = "bb402b8d4c85569410425650ce3eddc7d698ed96d39a73f941b08fb63082f1e7" dependencies = [ "unicode-segmentation", ] @@ -2733,7 +2771,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -2744,7 +2782,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -2818,7 +2856,7 @@ checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -2839,7 +2877,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -2849,7 +2887,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -2876,10 +2914,9 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ - "convert_case", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", "unicode-xid", ] @@ -2889,9 +2926,10 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" dependencies = [ + "convert_case", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", "unicode-xid", ] @@ -3000,7 +3038,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -3025,7 +3063,7 @@ checksum = "8dc51d98e636f5e3b0759a39257458b22619cac7e96d932da6eeb052891bb67c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -3157,7 +3195,7 @@ checksum = "2f9ed6b3789237c8a0c1c505af1c7eb2c560df6186f01b098c3a1064ea532f38" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -3178,14 +3216,14 @@ checksum = "c7f84e12ccf0a7ddc17a6c41c93326024c42920d7ee630d04950e6926645c0fe" [[package]] name = "env_logger" -version = "0.11.6" +version = "0.11.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcaee3d8e3cfc3fd92428d477bc97fc29ec8716d180c0d74c643bb26166660e0" +checksum = "c3716d7a920fb4fac5d84e9d4bce8ceb321e9414b4409da61b07b75c1e3d0697" dependencies = [ "anstream", "anstyle", "env_filter", - "humantime", + "jiff 0.2.4", "log", ] @@ -3263,7 +3301,7 @@ dependencies = [ "ahash", "alloy-dyn-abi", "alloy-primitives", - "indexmap 2.7.1", + "indexmap 2.8.0", ] [[package]] @@ -3315,12 +3353,12 @@ dependencies = [ [[package]] name = "fd-lock" -version = "4.0.3" +version = "4.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c44818c96aec5cadc9dacfb97bbcbcfc19a0de75b218412d56f57fbaab94e439" +checksum = "0ce92ff622d6dadf7349484f42c93271a0d49b7cc4d466a936405bacbe10aa78" dependencies = [ "cfg-if", - "rustix 0.38.44", + "rustix 1.0.2", "windows-sys 0.59.0", ] @@ -3336,9 +3374,9 @@ dependencies = [ [[package]] name = "ff" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" dependencies = [ "rand_core 0.6.4", "subtle", @@ -3507,7 +3545,7 @@ name = "forge-doc" version = "1.0.0" dependencies = [ "alloy-primitives", - "derive_more 1.0.0", + "derive_more 2.0.1", "eyre", "forge-fmt", "foundry-common", @@ -3616,7 +3654,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -4047,7 +4085,7 @@ version = "1.0.0" dependencies = [ "alloy-primitives", "alloy-sol-types", - "derive_more 1.0.0", + "derive_more 2.0.1", "foundry-common-fmt", "foundry-macros", "foundry-test-utils", @@ -4194,7 +4232,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -4354,7 +4392,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -4532,7 +4570,7 @@ checksum = "c57c477b645ee248b173bb1176b52dd528872f12c50375801a58aaf5ae91113f" dependencies = [ "bstr", "itoa", - "jiff", + "jiff 0.1.29", "thiserror 2.0.12", ] @@ -4754,7 +4792,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.7.1", + "indexmap 2.8.0", "slab", "tokio", "tokio-util", @@ -4773,7 +4811,7 @@ dependencies = [ "futures-core", "futures-sink", "http 1.2.0", - "indexmap 2.7.1", + "indexmap 2.8.0", "slab", "tokio", "tokio-util", @@ -4911,7 +4949,7 @@ dependencies = [ "markup5ever", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -5254,7 +5292,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -5336,7 +5374,7 @@ checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -5364,9 +5402,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.7.1" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" +checksum = "3954d50fe15b02142bf25d3b8bdadb634ec3948f103d04ffe3031bc8fe9d7058" dependencies = [ "arbitrary", "equivalent", @@ -5454,7 +5492,7 @@ dependencies = [ "indoc", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -5551,6 +5589,30 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "jiff" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d699bc6dfc879fb1bf9bdff0d4c56f0884fc6f0d0eb0fba397a6d00cd9a6b85e" +dependencies = [ + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde", +] + +[[package]] +name = "jiff-static" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d16e75759ee0aa64c57a56acbf43916987b20c77373cb7e808979e02b93c9f9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + [[package]] name = "jiff-tzdb" version = "0.1.3" @@ -5880,9 +5942,9 @@ dependencies = [ [[package]] name = "mdbook" -version = "0.4.46" +version = "0.4.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85c54109598152e19add1933b223b1913bcd16e27cbd7c2783269fe2f9a6cbdc" +checksum = "7e1a8fe3a4a01f28dab245c474cb7b95ccb4d3d2f17a5419a3d949f474c45e84" dependencies = [ "ammonia", "anyhow", @@ -5963,7 +6025,7 @@ checksum = "bf45bf44ab49be92fd1227a3be6fc6f617f1a337c06af54981048574d8783147" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -6053,7 +6115,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -6297,7 +6359,7 @@ checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -6339,9 +6401,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.20.3" +version = "1.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" +checksum = "cde51589ab56b20a6f686b2c68f7a0bd6add753d697abf720d63f8db3ab7b1ad" [[package]] name = "op-alloy-consensus" @@ -6456,7 +6518,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -6539,7 +6601,7 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -6598,7 +6660,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -6619,7 +6681,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.7.1", + "indexmap 2.8.0", ] [[package]] @@ -6672,7 +6734,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -6721,7 +6783,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -6775,11 +6837,11 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.20" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ - "zerocopy 0.7.35", + "zerocopy 0.8.23", ] [[package]] @@ -6821,7 +6883,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1ccf34da56fc294e7d4ccf69a85992b7dfb826b7cf57bac6a70bba3494cc08a" dependencies = [ "proc-macro2", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -6896,7 +6958,7 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -6916,7 +6978,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", "version_check", "yansi", ] @@ -6928,7 +6990,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d35f4dc9988d1326b065b4def5e950c3ed727aa03e3151b86cc9e2aec6b03f54" dependencies = [ "futures", - "indexmap 2.7.1", + "indexmap 2.8.0", "nix 0.29.0", "tokio", "tracing", @@ -6984,7 +7046,7 @@ checksum = "4ee1c9ac207483d5e7db4940700de86a9aae46ef90c48b57f99fe7edb8345e49" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -7007,7 +7069,7 @@ dependencies = [ "itertools 0.14.0", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -7070,7 +7132,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ed1a693391a16317257103ad06a88c6529ac640846021da7c435a06fffdacd7" dependencies = [ "chrono", - "indexmap 2.7.1", + "indexmap 2.8.0", "newtype-uuid", "quick-xml 0.37.2", "strip-ansi-escapes", @@ -7423,9 +7485,9 @@ dependencies = [ [[package]] name = "revm" -version = "19.5.0" +version = "19.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc5bef3c95fadf3b6a24a253600348380c169ef285f9780a793bb7090c8990d" +checksum = "7b906766b7ba049b515848952b5ae74f363d456e98de2021048a513e442b4f42" dependencies = [ "auto_impl", "cfg-if", @@ -7675,9 +7737,9 @@ dependencies = [ [[package]] name = "rustix" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dade4812df5c384711475be5fcd8c162555352945401aed22a35bffeab61f657" +checksum = "f7178faa4b75a30e269c71e61c353ce2748cf3d76f0c44c393f4e60abf49b825" dependencies = [ "bitflags 2.9.0", "errno", @@ -7898,7 +7960,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -7937,9 +7999,9 @@ dependencies = [ [[package]] name = "sdd" -version = "3.0.7" +version = "3.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b07779b9b918cc05650cb30f404d4d7835d26df37c235eded8a6832e2fb82cca" +checksum = "584e070911c7017da6cb2eb0788d09f43d789029b5877d3e5ecc8acf86ceee21" [[package]] name = "sec1" @@ -8059,22 +8121,22 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.218" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.218" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -8085,7 +8147,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -8094,7 +8156,7 @@ version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" dependencies = [ - "indexmap 2.7.1", + "indexmap 2.8.0", "itoa", "memchr", "ryu", @@ -8129,7 +8191,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -8163,7 +8225,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.7.1", + "indexmap 2.8.0", "serde", "serde_derive", "serde_json", @@ -8180,7 +8242,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -8215,7 +8277,7 @@ checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -8481,7 +8543,7 @@ checksum = "71d07263243b313296eca18f18eda3a190902dc3284bf67ceff29b8b54dac3e6" dependencies = [ "bumpalo", "index_vec", - "indexmap 2.7.1", + "indexmap 2.8.0", "parking_lot", "rayon", "rustc-hash", @@ -8524,7 +8586,7 @@ checksum = "970d7c774741f786d62cab78290e47d845b0b9c0c9d094a1642aced1d7946036" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -8696,7 +8758,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -8709,7 +8771,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -8777,9 +8839,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.99" +version = "2.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e02e925281e18ffd9d640e234264753c43edc62d64b2d4cf898f1bc5e75f3fc2" +checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" dependencies = [ "proc-macro2", "quote", @@ -8795,7 +8857,7 @@ dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -8815,7 +8877,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -8834,7 +8896,7 @@ dependencies = [ "fastrand", "getrandom 0.3.1", "once_cell", - "rustix 1.0.1", + "rustix 1.0.2", "windows-sys 0.59.0", ] @@ -8866,7 +8928,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45c6481c4829e4cc63825e62c49186a34538b7b2750b73b266581ffb612fb5ed" dependencies = [ - "rustix 1.0.1", + "rustix 1.0.2", "windows-sys 0.59.0", ] @@ -8925,7 +8987,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -8936,7 +8998,7 @@ checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -9071,7 +9133,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -9174,7 +9236,7 @@ version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148" dependencies = [ - "indexmap 2.7.1", + "indexmap 2.8.0", "serde", "serde_spanned", "toml_datetime", @@ -9196,7 +9258,7 @@ version = "0.22.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" dependencies = [ - "indexmap 2.7.1", + "indexmap 2.8.0", "serde", "serde_spanned", "toml_datetime", @@ -9347,7 +9409,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -9784,7 +9846,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", "wasm-bindgen-shared", ] @@ -9819,7 +9881,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -10064,7 +10126,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -10075,7 +10137,7 @@ checksum = "83577b051e2f49a058c308f17f273b570a6a758386fc291b5f6a934dd84e48c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -10086,7 +10148,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -10097,7 +10159,7 @@ checksum = "cb26fd936d991781ea39e87c3a27285081e3c0da5ca0fcbc02d368cc6f52ff01" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -10474,7 +10536,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", "synstructure", ] @@ -10484,7 +10546,6 @@ version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ - "byteorder", "zerocopy-derive 0.7.35", ] @@ -10505,7 +10566,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -10516,7 +10577,7 @@ checksum = "6352c01d0edd5db859a63e2605f4ea3183ddbd15e2c4a9e7d32184df75e4f154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -10536,7 +10597,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", "synstructure", ] @@ -10557,7 +10618,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -10579,7 +10640,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.100", ] [[package]] @@ -10594,7 +10655,7 @@ dependencies = [ "crossbeam-utils", "displaydoc", "flate2", - "indexmap 2.7.1", + "indexmap 2.8.0", "memchr", "thiserror 2.0.12", "zopfli", diff --git a/Cargo.toml b/Cargo.toml index 0811a200fec91..eae5e6f6e266c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -255,7 +255,7 @@ proc-macro2 = "1.0" quote = "1.0" syn = "2.0" async-trait = "0.1" -derive_more = { version = "1.0", features = ["full"] } +derive_more = { version = "2.0", features = ["full"] } thiserror = "2" # bench diff --git a/crates/cast/bin/cmd/storage.rs b/crates/cast/bin/cmd/storage.rs index c7a90ad2f06b5..c51511c423487 100644 --- a/crates/cast/bin/cmd/storage.rs +++ b/crates/cast/bin/cmd/storage.rs @@ -51,6 +51,10 @@ pub struct StorageArgs { #[arg(value_parser = parse_slot)] slot: Option, + /// The known proxy address. If provided, the storage layout is retrieved from this address. + #[arg(long,value_parser = NameOrAddress::from_str)] + proxy: Option, + /// The block height to query at. /// /// Can also be the tags earliest, finalized, safe, latest, or pending. @@ -134,7 +138,11 @@ impl StorageArgs { let chain = utils::get_chain(config.chain, &provider).await?; let api_key = config.get_etherscan_api_key(Some(chain)).unwrap_or_default(); let client = Client::new(chain, api_key)?; - let source = find_source(client, address).await?; + let source = if let Some(proxy) = self.proxy { + find_source(client, proxy.resolve(&provider).await?).await? + } else { + find_source(client, address).await? + }; let metadata = source.items.first().unwrap(); if metadata.is_vyper() { eyre::bail!("Contract at provided address is not a valid Solidity contract") diff --git a/crates/cast/tests/cli/main.rs b/crates/cast/tests/cli/main.rs index e88ade5f28489..509caf0efd468 100644 --- a/crates/cast/tests/cli/main.rs +++ b/crates/cast/tests/cli/main.rs @@ -1295,6 +1295,48 @@ casttest!(storage_layout_complex, |_prj, cmd| { ╰-------------------------------+--------------------------------------------------------------------+------+--------+-------+--------------------------------------------------+--------------------------------------------------------------------+---------------------------------╯ +"#]]); +}); + +casttest!(storage_layout_complex_proxy, |_prj, cmd| { + cmd.args([ + "storage", + "--rpc-url", + next_rpc_endpoint(NamedChain::Sepolia).as_str(), + "--block", + "7857852", + "--etherscan-api-key", + next_mainnet_etherscan_api_key().as_str(), + "0xE2588A9CAb7Ea877206E35f615a39f84a64A7A3b", + "--proxy", + "0x29fcb43b46531bca003ddc8fcb67ffe91900c762" + ]) + .assert_success() + .stdout_eq(str![[r#" + +╭----------------------------+-------------------------------------------------+------+--------+-------+--------------------------------------------------+--------------------------------------------------------------------+-----------------------------╮ +| Name | Type | Slot | Offset | Bytes | Value | Hex Value | Contract | ++============================================================================================================================================================================================================================================================+ +| singleton | address | 0 | 0 | 20 | 239704109775411986678417050956533140837380441954 | 0x00000000000000000000000029fcb43b46531bca003ddc8fcb67ffe91900c762 | contracts/SafeL2.sol:SafeL2 | +|----------------------------+-------------------------------------------------+------+--------+-------+--------------------------------------------------+--------------------------------------------------------------------+-----------------------------| +| modules | mapping(address => address) | 1 | 0 | 32 | 0 | 0x0000000000000000000000000000000000000000000000000000000000000000 | contracts/SafeL2.sol:SafeL2 | +|----------------------------+-------------------------------------------------+------+--------+-------+--------------------------------------------------+--------------------------------------------------------------------+-----------------------------| +| owners | mapping(address => address) | 2 | 0 | 32 | 0 | 0x0000000000000000000000000000000000000000000000000000000000000000 | contracts/SafeL2.sol:SafeL2 | +|----------------------------+-------------------------------------------------+------+--------+-------+--------------------------------------------------+--------------------------------------------------------------------+-----------------------------| +| ownerCount | uint256 | 3 | 0 | 32 | 1 | 0x0000000000000000000000000000000000000000000000000000000000000001 | contracts/SafeL2.sol:SafeL2 | +|----------------------------+-------------------------------------------------+------+--------+-------+--------------------------------------------------+--------------------------------------------------------------------+-----------------------------| +| threshold | uint256 | 4 | 0 | 32 | 1 | 0x0000000000000000000000000000000000000000000000000000000000000001 | contracts/SafeL2.sol:SafeL2 | +|----------------------------+-------------------------------------------------+------+--------+-------+--------------------------------------------------+--------------------------------------------------------------------+-----------------------------| +| nonce | uint256 | 5 | 0 | 32 | 0 | 0x0000000000000000000000000000000000000000000000000000000000000000 | contracts/SafeL2.sol:SafeL2 | +|----------------------------+-------------------------------------------------+------+--------+-------+--------------------------------------------------+--------------------------------------------------------------------+-----------------------------| +| _deprecatedDomainSeparator | bytes32 | 6 | 0 | 32 | 0 | 0x0000000000000000000000000000000000000000000000000000000000000000 | contracts/SafeL2.sol:SafeL2 | +|----------------------------+-------------------------------------------------+------+--------+-------+--------------------------------------------------+--------------------------------------------------------------------+-----------------------------| +| signedMessages | mapping(bytes32 => uint256) | 7 | 0 | 32 | 0 | 0x0000000000000000000000000000000000000000000000000000000000000000 | contracts/SafeL2.sol:SafeL2 | +|----------------------------+-------------------------------------------------+------+--------+-------+--------------------------------------------------+--------------------------------------------------------------------+-----------------------------| +| approvedHashes | mapping(address => mapping(bytes32 => uint256)) | 8 | 0 | 32 | 0 | 0x0000000000000000000000000000000000000000000000000000000000000000 | contracts/SafeL2.sol:SafeL2 | +╰----------------------------+-------------------------------------------------+------+--------+-------+--------------------------------------------------+--------------------------------------------------------------------+-----------------------------╯ + + "#]]); }); diff --git a/crates/forge/tests/cli/script.rs b/crates/forge/tests/cli/script.rs index aaf0658c65ac3..465d3db337590 100644 --- a/crates/forge/tests/cli/script.rs +++ b/crates/forge/tests/cli/script.rs @@ -1953,7 +1953,7 @@ contract SimpleScript is Script { .assert_success() .stdout_eq(str![[r#" {"logs":[],"returns":{"success":{"internal_type":"bool","value":"true"}},"success":true,"raw_logs":[],"traces":[["Deployment",{"arena":[{"parent":null,"children":[],"idx":0,"trace":{"depth":0,"success":true,"caller":"0x1804c8ab1f12e6bbf3894d4083f33e07309d1f38","address":"0x5b73c5498c1e3b4dba84de0f1833c4a029d90519","maybe_precompile":false,"selfdestruct_address":null,"selfdestruct_refund_target":null,"selfdestruct_transferred_value":null,"kind":"CREATE","value":"0x0","data":"[..]","output":"[..]","gas_used":"{...}","gas_limit":"{...}","status":"Return","steps":[],"decoded":{"label":null,"return_data":null,"call_data":null}},"logs":[],"ordering":[]}]}],["Execution",{"arena":[{"parent":null,"children":[1,2],"idx":0,"trace":{"depth":0,"success":true,"caller":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","address":"0x5b73c5498c1e3b4dba84de0f1833c4a029d90519","maybe_precompile":null,"selfdestruct_address":null,"selfdestruct_refund_target":null,"selfdestruct_transferred_value":null,"kind":"CALL","value":"0x0","data":"0xc0406226","output":"0x0000000000000000000000000000000000000000000000000000000000000001","gas_used":"{...}","gas_limit":1073720760,"status":"Return","steps":[],"decoded":{"label":null,"return_data":null,"call_data":null}},"logs":[],"ordering":[{"Call":0},{"Call":1}]},{"parent":0,"children":[],"idx":1,"trace":{"depth":1,"success":true,"caller":"0x5b73c5498c1e3b4dba84de0f1833c4a029d90519","address":"0x7109709ecfa91a80626ff3989d68f67f5b1dd12d","maybe_precompile":null,"selfdestruct_address":null,"selfdestruct_refund_target":null,"selfdestruct_transferred_value":null,"kind":"CALL","value":"0x0","data":"0x7fb5297f","output":"0x","gas_used":"{...}","gas_limit":1056940994,"status":"Return","steps":[],"decoded":{"label":null,"return_data":null,"call_data":null}},"logs":[],"ordering":[]},{"parent":0,"children":[],"idx":2,"trace":{"depth":1,"success":true,"caller":"0x5b73c5498c1e3b4dba84de0f1833c4a029d90519","address":"0x0000000000000000000000000000000000000000","maybe_precompile":null,"selfdestruct_address":null,"selfdestruct_refund_target":null,"selfdestruct_transferred_value":null,"kind":"CALL","value":"0x0","data":"0x","output":"0x","gas_used":"{...}","gas_limit":1056940645,"status":"Stop","steps":[],"decoded":{"label":null,"return_data":null,"call_data":null}},"logs":[],"ordering":[]}]}]],"gas_used":"{...}","labeled_addresses":{},"returned":"0x0000000000000000000000000000000000000000000000000000000000000001","address":null} -{"chain":31337,"estimated_gas_price":"{...}","estimated_total_gas_used":"{...}","estimated_amount_required":"{...}"} +{"chain":31337,"estimated_gas_price":"{...}","estimated_total_gas_used":"{...}","estimated_amount_required":"{...}","token_symbol":"ETH"} {"chain":"anvil-hardhat","status":"success","tx_hash":"0x4f78afe915fceb282c7625a68eb350bc0bf78acb59ad893e5c62b710a37f3156","contract_address":null,"block_number":1,"gas_used":"{...}","gas_price":"{...}"} {"status":"success","transactions":"[..]/broadcast/Foo.sol/31337/run-latest.json","sensitive":"[..]/cache/Foo.sol/31337/run-latest.json"} diff --git a/crates/script/src/simulate.rs b/crates/script/src/simulate.rs index cf6aeb349436b..a58b1058ebc2e 100644 --- a/crates/script/src/simulate.rs +++ b/crates/script/src/simulate.rs @@ -9,6 +9,7 @@ use crate::{ sequence::get_commit_hash, ScriptArgs, ScriptConfig, ScriptResult, }; +use alloy_chains::NamedChain; use alloy_network::TransactionBuilder; use alloy_primitives::{map::HashMap, utils::format_units, Address, Bytes, TxKind, U256}; use dialoguer::Confirm; @@ -346,6 +347,12 @@ impl FilledTransactionsState { for (rpc, total_gas) in total_gas_per_rpc { let provider_info = manager.get(&rpc).expect("provider is set."); + // Get the native token symbol for the chain using NamedChain + let token_symbol = NamedChain::try_from(provider_info.chain) + .unwrap_or_default() + .native_currency_symbol() + .unwrap_or("ETH"); + // We don't store it in the transactions, since we want the most updated value. // Right before broadcasting. let per_gas = if let Some(gas_price) = self.args.with_gas_price { @@ -369,7 +376,7 @@ impl FilledTransactionsState { sh_println!("\nEstimated gas price: {} gwei", estimated_gas_price)?; sh_println!("\nEstimated total gas used for script: {total_gas}")?; - sh_println!("\nEstimated amount required: {estimated_amount} ETH",)?; + sh_println!("\nEstimated amount required: {estimated_amount} {token_symbol}")?; sh_println!("\n==========================")?; } else { sh_println!( @@ -379,6 +386,7 @@ impl FilledTransactionsState { "estimated_gas_price": estimated_gas_price, "estimated_total_gas_used": total_gas, "estimated_amount_required": estimated_amount, + "token_symbol": token_symbol, }) )?; } diff --git a/crates/test-utils/src/util.rs b/crates/test-utils/src/util.rs index f2b71064f1f56..75f39bf1d2e2e 100644 --- a/crates/test-utils/src/util.rs +++ b/crates/test-utils/src/util.rs @@ -1017,7 +1017,10 @@ fn test_redactions() -> snapbox::Redactions { ("[SAVED_SENSITIVE_VALUES]", r"Sensitive values saved to: .*\.json"), ("[ESTIMATED_GAS_PRICE]", r"Estimated gas price:\s*(\d+(\.\d+)?)\s*gwei"), ("[ESTIMATED_TOTAL_GAS_USED]", r"Estimated total gas used for script: \d+"), - ("[ESTIMATED_AMOUNT_REQUIRED]", r"Estimated amount required:\s*(\d+(\.\d+)?)\s*ETH"), + ( + "[ESTIMATED_AMOUNT_REQUIRED]", + r"Estimated amount required:\s*(\d+(\.\d+)?)\s*[A-Z]{3}", + ), ]; for (placeholder, re) in redactions { r.insert(placeholder, Regex::new(re).expect(re)).expect(re); diff --git a/crates/verify/src/etherscan/mod.rs b/crates/verify/src/etherscan/mod.rs index eece0c928064d..e61d5e1b07f5c 100644 --- a/crates/verify/src/etherscan/mod.rs +++ b/crates/verify/src/etherscan/mod.rs @@ -278,8 +278,13 @@ impl EtherscanVerificationProvider { builder = if let Some(api_url) = api_url { // we don't want any trailing slashes because this can cause cloudflare issues: let api_url = api_url.trim_end_matches('/'); - let base_url = if *verifier_type != VerificationProviderType::Etherscan { - // If verifier is not Etherscan then set base url as api url without trialing /api. + + // Verifier is etherscan if explicitly set or if no verifier set (default sourcify) but + // API key passed. + let is_etherscan = verifier_type.is_etherscan() || + (verifier_type.is_sourcify() && etherscan_key.is_some()); + let base_url = if !is_etherscan { + // If verifier is not Etherscan then set base url as api url without /api suffix. api_url.strip_prefix("/api").unwrap_or(api_url) } else { base_url.unwrap_or(api_url) diff --git a/crates/verify/src/provider.rs b/crates/verify/src/provider.rs index 07f1e09ea6aa3..01a06332a36ce 100644 --- a/crates/verify/src/provider.rs +++ b/crates/verify/src/provider.rs @@ -170,8 +170,9 @@ pub enum VerificationProviderType { impl VerificationProviderType { /// Returns the corresponding `VerificationProvider` for the key pub fn client(&self, key: Option<&str>) -> Result> { - // 1. If `--verifier sourcify` is set, always use Sourcify. - if matches!(self, Self::Sourcify) { + let has_key = key.as_ref().is_some_and(|k| !k.is_empty()); + // 1. If no verifier or `--verifier sourcify` is set and no API key provided, use Sourcify. + if !has_key && self.is_sourcify() { sh_println!( "Attempting to verify on Sourcify. Pass the --etherscan-api-key to verify on Etherscan, \ or use the --verifier flag to verify on another provider." @@ -180,8 +181,8 @@ impl VerificationProviderType { } // 2. If `--verifier etherscan` is explicitly set, enforce the API key requirement. - if matches!(self, Self::Etherscan) { - if key.as_ref().is_none_or(|key| key.is_empty()) { + if self.is_etherscan() { + if !has_key { eyre::bail!("ETHERSCAN_API_KEY must be set to use Etherscan as a verifier") } return Ok(Box::::default()); @@ -194,11 +195,19 @@ impl VerificationProviderType { } // 4. If no `--verifier` is specified but `ETHERSCAN_API_KEY` is set, default to Etherscan. - if key.as_ref().is_some_and(|k| !k.is_empty()) { + if has_key { return Ok(Box::::default()); } // 5. If no valid provider is specified, bail. eyre::bail!("No valid verification provider specified. Pass the --verifier flag to specify a provider or set the ETHERSCAN_API_KEY environment variable to use Etherscan as a verifier.") } + + pub fn is_sourcify(&self) -> bool { + matches!(self, Self::Sourcify) + } + + pub fn is_etherscan(&self) -> bool { + matches!(self, Self::Etherscan) + } } diff --git a/deny.toml b/deny.toml index ac92742909a18..33c5a4233e55d 100644 --- a/deny.toml +++ b/deny.toml @@ -11,6 +11,8 @@ ignore = [ "RUSTSEC-2024-0436", # https://rustsec.org/advisories/RUSTSEC-2024-0437 protobuf! Crash due to uncontrolled recursion in protobuf crate. "RUSTSEC-2024-0437", + # humantime is unmaintained + "RUSTSEC-2025-0014", ] # This section is considered when running `cargo deny check bans`. @@ -47,7 +49,6 @@ allow = [ "BSD-3-Clause", "ISC", "Unicode-3.0", - "OpenSSL", "Unlicense", "WTFPL", "BSL-1.0", From 2802d43da3811c20c0fcec2454fd326921fb47d9 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Sat, 15 Mar 2025 12:59:39 +0700 Subject: [PATCH 023/232] const LATEST_SOLC: Version = Version::new(0, 8, 29); (#28) * feat(forge): allow path in forge selectors upload (#10073) * feat(forge): allow path in forge selectors upload * Changes after review: reuse PathOrContractInfo * feat: add `x86_64-musl` and `aarch64-musl` release targets (#9984) * feat: add `x86_64` and `aarch64` musl targets * feat: update nextest matrices * try with aarch64 targets * feat: define granular linux targets and restore `aarch64` one * revert `matrices.py` file * chore: reenable impersonate test (#10076) * feat: solc 0.8.29 (#10078) * feat: solc 0.8.29 * update match --------- Co-authored-by: grandizzy <38490174+grandizzy@users.noreply.github.com> Co-authored-by: Giovanni Napoli Co-authored-by: Matthias Seitz --- .github/workflows/release.yml | 10 ++++ Cargo.lock | 59 ++++++------------- Cargo.toml | 2 +- crates/cast/tests/cli/main.rs | 69 ++++++++++------------ crates/config/src/utils.rs | 3 +- crates/forge/bin/cmd/selectors.rs | 27 +++++++-- crates/forge/tests/cli/odyssey.rs | 6 ++ crates/forge/tests/cli/svm.rs | 8 ++- crates/forge/tests/cli/test_cmd.rs | 95 ++++++++++++++++++++++++++++++ crates/test-utils/src/util.rs | 4 +- 10 files changed, 196 insertions(+), 87 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2e0b5739e8ce7..b798ea6fd68fa 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -94,11 +94,21 @@ jobs: svm_target_platform: linux-amd64 platform: linux arch: amd64 + - runner: Linux-20.04 + target: x86_64-unknown-linux-musl + svm_target_platform: linux-amd64 + platform: linux + arch: amd64 - runner: Linux-20.04 target: aarch64-unknown-linux-gnu svm_target_platform: linux-aarch64 platform: linux arch: arm64 + - runner: Linux-20.04 + target: aarch64-unknown-linux-musl + svm_target_platform: linux-aarch64 + platform: linux + arch: arm64 # This is pinned to `macos-13-large` to support old SDK versions. # If the runner is deprecated it should be pinned to the oldest available version of the runner. - runner: macos-13-large diff --git a/Cargo.lock b/Cargo.lock index 48d28ddf548d1..5224c76930bac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2191,7 +2191,7 @@ dependencies = [ "alloy-json-abi", "alloy-primitives", "clap", - "dirs 6.0.0", + "dirs", "eyre", "forge-fmt", "foundry-cli", @@ -2958,22 +2958,13 @@ dependencies = [ "subtle", ] -[[package]] -name = "dirs" -version = "5.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" -dependencies = [ - "dirs-sys 0.4.1", -] - [[package]] name = "dirs" version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" dependencies = [ - "dirs-sys 0.5.0", + "dirs-sys", ] [[package]] @@ -2986,18 +2977,6 @@ dependencies = [ "dirs-sys-next", ] -[[package]] -name = "dirs-sys" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" -dependencies = [ - "libc", - "option-ext", - "redox_users 0.4.6", - "windows-sys 0.48.0", -] - [[package]] name = "dirs-sys" version = "0.5.0" @@ -3882,15 +3861,15 @@ dependencies = [ [[package]] name = "foundry-compilers" -version = "0.13.3" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac8f0bab060fd7c1764c4be2563e6933d39ec8c2b8a8d6c08aaf45ab29d08310" +checksum = "21089dce1284b88283a6dc1684b22347debb517e86f7e0033e1cf277fda3ea7e" dependencies = [ "alloy-json-abi", "alloy-primitives", "auto_impl", "derive_more 1.0.0", - "dirs 6.0.0", + "dirs", "dyn-clone", "foundry-compilers-artifacts", "foundry-compilers-core", @@ -3919,9 +3898,9 @@ dependencies = [ [[package]] name = "foundry-compilers-artifacts" -version = "0.13.3" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b102dd131e939d80cc5c85214d2f0f6ba20ed75cf098019c4d995791b4ebae05" +checksum = "c6cc7a5aec89a3e0f271ec522aac586f97d9104c3b31563716f9ca20113e7f5c" dependencies = [ "foundry-compilers-artifacts-solc", "foundry-compilers-artifacts-vyper", @@ -3929,9 +3908,9 @@ dependencies = [ [[package]] name = "foundry-compilers-artifacts-solc" -version = "0.13.3" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db9ef02de4fda04ae3ed098afb6e16edd742d1073f972197a4566836b453bdcd" +checksum = "c0c1058532f7a062f9bba3cd807f74e034b2f37f8a27d8bcccabdc104102f847" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -3953,9 +3932,9 @@ dependencies = [ [[package]] name = "foundry-compilers-artifacts-vyper" -version = "0.13.3" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bd9d33cbeda448af917105920fefdc3ac42f9ffdaa2d840d58207db7807ea29" +checksum = "33f5f4621a0fad72868c5174c01bbfdfb16a6a650edd2f4a41cf5e5dc611a15e" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -3968,9 +3947,9 @@ dependencies = [ [[package]] name = "foundry-compilers-core" -version = "0.13.3" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "746d121f7b86b84b20e582a27a56c49435768ad3b8005e9afeaf68b53a77fb5c" +checksum = "3de4acbffff75510c230626f2c3071efa1d6c031afc821a8ed410b67ee6958dd" dependencies = [ "alloy-primitives", "cfg-if", @@ -3995,7 +3974,7 @@ dependencies = [ "Inflector", "alloy-chains", "alloy-primitives", - "dirs 6.0.0", + "dirs", "dunce", "eyre", "figment", @@ -8780,12 +8759,12 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "svm-rs" -version = "0.5.11" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4197826bb07b996788b9860a95a1fe2c1307b2404a8c66f5ba825c42532b7c3c" +checksum = "9a30a58b94c1ddc5f07a428d16e58e8f4c7cee9e67130cda12ed148f5ef98fff" dependencies = [ "const-hex", - "dirs 5.0.1", + "dirs", "fs4", "reqwest", "semver 1.0.26", @@ -8800,9 +8779,9 @@ dependencies = [ [[package]] name = "svm-rs-builds" -version = "0.5.11" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "074faea21171905847a96135b3896e2e0b74373758ca07b96a41c646cc04a8e5" +checksum = "ebddc0ea9fd9fb61d0de9585a99c58f87e8c14b8811726a57cc5f5b1a029585e" dependencies = [ "build_const", "const-hex", diff --git a/Cargo.toml b/Cargo.toml index eae5e6f6e266c..b55f708db90cc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -188,7 +188,7 @@ foundry-linking = { path = "crates/linking" } # solc & compilation utilities foundry-block-explorers = { version = "0.11.0", default-features = false } -foundry-compilers = { version = "0.13.3", default-features = false } +foundry-compilers = { version = "0.13.5", default-features = false } foundry-fork-db = "0.12" solang-parser = "=0.3.3" solar-parse = { version = "=0.1.1", default-features = false } diff --git a/crates/cast/tests/cli/main.rs b/crates/cast/tests/cli/main.rs index 06c5e61167f16..2d1ad75854999 100644 --- a/crates/cast/tests/cli/main.rs +++ b/crates/cast/tests/cli/main.rs @@ -2032,43 +2032,38 @@ forgetest_async!(cast_call_custom_chain_id, |_prj, cmd| { }); // https://github.com/foundry-rs/foundry/issues/9541 -forgetest_async!( - // ignore for now, fails with "json: unsupported value: NaN" - #[ignore] - cast_run_impersonated_tx, - |_prj, cmd| { - let (_api, handle) = anvil::spawn( - NodeConfig::test() - .with_auto_impersonate(true) - .with_eth_rpc_url(Some("https://sepolia.base.org")), - ) - .await; - - let http_endpoint = handle.http_endpoint(); - - let provider = ProviderBuilder::new().on_http(http_endpoint.parse().unwrap()); - - // send impersonated tx - let tx = TransactionRequest::default() - .with_from(address!("041563c07028Fc89106788185763Fc73028e8511")) - .with_to(address!("F38aA5909D89F5d98fCeA857e708F6a6033f6CF8")) - .with_input( - Bytes::from_str( - "0x60fe47b1000000000000000000000000000000000000000000000000000000000000000c", - ) - .unwrap(), - ); - - let receipt = provider.send_transaction(tx).await.unwrap().get_receipt().await.unwrap(); - - assert!(receipt.status()); - - // run impersonated tx - cmd.cast_fuse() - .args(["run", &receipt.transaction_hash.to_string(), "--rpc-url", &http_endpoint]) - .assert_success(); - } -); +forgetest_async!(cast_run_impersonated_tx, |_prj, cmd| { + let (_api, handle) = anvil::spawn( + NodeConfig::test() + .with_auto_impersonate(true) + .with_eth_rpc_url(Some("https://sepolia.base.org")), + ) + .await; + + let http_endpoint = handle.http_endpoint(); + + let provider = ProviderBuilder::new().on_http(http_endpoint.parse().unwrap()); + + // send impersonated tx + let tx = TransactionRequest::default() + .with_from(address!("041563c07028Fc89106788185763Fc73028e8511")) + .with_to(address!("F38aA5909D89F5d98fCeA857e708F6a6033f6CF8")) + .with_input( + Bytes::from_str( + "0x60fe47b1000000000000000000000000000000000000000000000000000000000000000c", + ) + .unwrap(), + ); + + let receipt = provider.send_transaction(tx).await.unwrap().get_receipt().await.unwrap(); + + assert!(receipt.status()); + + // run impersonated tx + cmd.cast_fuse() + .args(["run", &receipt.transaction_hash.to_string(), "--rpc-url", &http_endpoint]) + .assert_success(); +}); // casttest!(fetch_src_blockscout, |_prj, cmd| { diff --git a/crates/config/src/utils.rs b/crates/config/src/utils.rs index 94f4823dc7cb5..86b25d1043797 100644 --- a/crates/config/src/utils.rs +++ b/crates/config/src/utils.rs @@ -263,6 +263,7 @@ pub fn evm_spec_id(evm_version: EvmVersion, odyssey: bool) -> SpecId { EvmVersion::Paris => SpecId::MERGE, EvmVersion::Shanghai => SpecId::SHANGHAI, EvmVersion::Cancun => SpecId::CANCUN, - EvmVersion::Prague => SpecId::OSAKA, // Osaka enables EOF + EvmVersion::Prague => SpecId::PRAGUE, + EvmVersion::Osaka => SpecId::OSAKA, } } diff --git a/crates/forge/bin/cmd/selectors.rs b/crates/forge/bin/cmd/selectors.rs index 56c25cc003cd6..9c2db2be8d8ec 100644 --- a/crates/forge/bin/cmd/selectors.rs +++ b/crates/forge/bin/cmd/selectors.rs @@ -7,7 +7,7 @@ use foundry_cli::{ utils::{cache_local_signatures, FoundryPathExt}, }; use foundry_common::{ - compile::{compile_target, ProjectCompiler}, + compile::{compile_target, PathOrContractInfo, ProjectCompiler}, selectors::{import_selectors, SelectorImportData}, }; use foundry_compilers::{artifacts::output_selection::ContractOutputSelection, info::ContractInfo}; @@ -36,8 +36,9 @@ pub enum SelectorsSubcommands { #[command(visible_alias = "up")] Upload { /// The name of the contract to upload selectors for. + /// Can also be in form of `path:contract name`. #[arg(required_unless_present = "all")] - contract: Option, + contract: Option, /// Upload selectors for all contracts in the project. #[arg(long, required_unless_present = "contract")] @@ -107,8 +108,15 @@ impl SelectorsSubcommands { }; let project = build_args.project()?; - let output = if let Some(name) = &contract { - let target_path = project.find_contract_path(name)?; + let output = if let Some(contract_info) = &contract { + let Some(contract_name) = contract_info.name() else { + eyre::bail!("No contract name provided.") + }; + + let target_path = contract_info + .path() + .map(Ok) + .unwrap_or_else(|| project.find_contract_path(contract_name))?; compile_target(&target_path, &project, false)? } else { ProjectCompiler::new().compile(&project)? @@ -125,8 +133,15 @@ impl SelectorsSubcommands { .map(|(_, contract, artifact)| (contract, artifact)) .collect() } else { - let contract = contract.unwrap(); - let found_artifact = output.find_first(&contract); + let contract_info = contract.unwrap(); + let contract = contract_info.name().unwrap().to_string(); + + let found_artifact = if let Some(path) = contract_info.path() { + output.find(project.root().join(path).as_path(), &contract) + } else { + output.find_first(&contract) + }; + let artifact = found_artifact .ok_or_else(|| { eyre::eyre!( diff --git a/crates/forge/tests/cli/odyssey.rs b/crates/forge/tests/cli/odyssey.rs index 7d98e79fcf082..f465c032bd134 100644 --- a/crates/forge/tests/cli/odyssey.rs +++ b/crates/forge/tests/cli/odyssey.rs @@ -1,3 +1,5 @@ +use foundry_compilers::artifacts::EvmVersion; + // Ensure we can run basic counter tests with EOF support. forgetest_init!(test_eof_flag, |prj, cmd| { if !has_docker() { @@ -5,6 +7,10 @@ forgetest_init!(test_eof_flag, |prj, cmd| { return; } + prj.update_config(|config| { + config.evm_version = EvmVersion::Osaka; + }); + cmd.forge_fuse().args(["test", "--eof"]).assert_success().stdout_eq(str![[r#" [COMPILING_FILES] with [SOLC_VERSION] [SOLC_VERSION] [ELAPSED] diff --git a/crates/forge/tests/cli/svm.rs b/crates/forge/tests/cli/svm.rs index e0c10a052e936..d585529da8e40 100644 --- a/crates/forge/tests/cli/svm.rs +++ b/crates/forge/tests/cli/svm.rs @@ -11,7 +11,7 @@ use svm::Platform; /// 3. svm bumped in foundry-compilers /// 4. foundry-compilers update with any breaking changes /// 5. upgrade the `LATEST_SOLC` -const LATEST_SOLC: Version = Version::new(0, 8, 27); +const LATEST_SOLC: Version = Version::new(0, 8, 29); macro_rules! ensure_svm_releases { ($($test:ident => $platform:ident),* $(,)?) => {$( @@ -57,6 +57,12 @@ contract CounterTest is Test {{ "# ); prj.add_test("Counter", &src).unwrap(); + + // we need to remove the pinned solc version for this + prj.update_config(|c| { + c.solc.take(); + }); + cmd.arg("test").assert_success().stdout_eq(str![[r#" ... Ran 1 test for test/Counter.sol:CounterTest diff --git a/crates/forge/tests/cli/test_cmd.rs b/crates/forge/tests/cli/test_cmd.rs index ce0f4b13f89d1..a13f8c51ba81a 100644 --- a/crates/forge/tests/cli/test_cmd.rs +++ b/crates/forge/tests/cli/test_cmd.rs @@ -3316,3 +3316,98 @@ Traces: "#]]); }); + +// +forgetest_init!(can_upload_selectors_with_path, |prj, cmd| { + prj.add_source( + "CounterV1.sol", + r#" +contract Counter { + uint256 public number; + + function setNumberV1(uint256 newNumber) public { + number = newNumber; + } + + function incrementV1() public { + number++; + } +} + "#, + ) + .unwrap(); + + prj.add_source( + "CounterV2.sol", + r#" +contract CounterV2 { + uint256 public number; + + function setNumberV2(uint256 newNumber) public { + number = newNumber; + } + + function incrementV2() public { + number++; + } +} + "#, + ) + .unwrap(); + + // Upload Counter without path fails as there are multiple contracts with same name. + cmd.args(["selectors", "upload", "Counter"]).assert_failure().stderr_eq(str![[r#" +... +Error: Multiple contracts found with the name `Counter` +... + +"#]]); + + // Upload without contract name should fail. + cmd.forge_fuse().args(["selectors", "upload", "src/Counter.sol"]).assert_failure().stderr_eq( + str![[r#" +... +Error: No contract name provided. +... + +"#]], + ); + + // Upload single CounterV2. + cmd.forge_fuse().args(["selectors", "upload", "CounterV2"]).assert_success().stdout_eq(str![[ + r#" +... +Uploading selectors for CounterV2... +... +Selectors successfully uploaded to OpenChain +... + +"# + ]]); + + // Upload CounterV1 with path. + cmd.forge_fuse() + .args(["selectors", "upload", "src/CounterV1.sol:Counter"]) + .assert_success() + .stdout_eq(str![[r#" +... +Uploading selectors for Counter... +... +Selectors successfully uploaded to OpenChain +... + +"#]]); + + // Upload Counter with path. + cmd.forge_fuse() + .args(["selectors", "upload", "src/Counter.sol:Counter"]) + .assert_success() + .stdout_eq(str![[r#" +... +Uploading selectors for Counter... +... +Selectors successfully uploaded to OpenChain +... + +"#]]); +}); diff --git a/crates/test-utils/src/util.rs b/crates/test-utils/src/util.rs index 75f39bf1d2e2e..3c2b0546f7061 100644 --- a/crates/test-utils/src/util.rs +++ b/crates/test-utils/src/util.rs @@ -213,7 +213,7 @@ impl ExtTester { } } -/// Initializes a project with `forge init` at the given path. +/// Initializes a project with `forge init` at the given path from a template directory. /// /// This should be called after an empty project is created like in /// [some of this crate's macros](crate::forgetest_init). @@ -226,6 +226,8 @@ 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. +/// +/// This sets the project's solc version to the [`SOLC_VERSION`]. #[allow(clippy::disallowed_macros)] pub fn initialize(target: &Path) { println!("initializing {}", target.display()); From eca7fc8c53535001016249581985038e1de0f7a3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 30 Mar 2025 18:39:47 +0700 Subject: [PATCH 024/232] chore(deps): bump zip in the cargo group across 1 directory (#31) Bumps the cargo group with 1 update in the / directory: [zip](https://github.com/zip-rs/zip2). Updates `zip` from 2.2.3 to 2.4.1 - [Release notes](https://github.com/zip-rs/zip2/releases) - [Changelog](https://github.com/zip-rs/zip2/blob/master/CHANGELOG.md) - [Commits](https://github.com/zip-rs/zip2/compare/v2.2.3...v2.4.1) --- updated-dependencies: - dependency-name: zip dependency-type: indirect dependency-group: cargo ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5224c76930bac..58a3082ed6709 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8537,7 +8537,7 @@ dependencies = [ "solar-config", "solar-data-structures", "solar-macros", - "thiserror 2.0.12", + "thiserror 1.0.69", "tracing", "unicode-width 0.2.0", ] @@ -8772,7 +8772,7 @@ dependencies = [ "serde_json", "sha2", "tempfile", - "thiserror 2.0.12", + "thiserror 1.0.69", "url", "zip", ] @@ -10609,9 +10609,9 @@ dependencies = [ [[package]] name = "zip" -version = "2.2.3" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b280484c454e74e5fff658bbf7df8fdbe7a07c6b2de4a53def232c15ef138f3a" +checksum = "938cc23ac49778ac8340e366ddc422b2227ea176edb447e23fc0627608dddadd" dependencies = [ "arbitrary", "bzip2", From e24df49cb7a20c65b66ae095613761b8cf9d60b6 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Sun, 30 Mar 2025 20:12:34 +0700 Subject: [PATCH 025/232] Add .circleci/config.yml (#33) From f62dc844821b4f224f90969790ced81a87dab791 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Sun, 30 Mar 2025 20:46:08 +0700 Subject: [PATCH 026/232] Revert "python3-compile-vyper-contract (#27)" (#34) This reverts commit c235592917161f2eba6ec443739e84e524de9174. --- .github/workflows/nextest.yml | 4 +- Cargo.lock | 347 ++++++++++++----------------- Cargo.toml | 2 +- crates/cast/bin/cmd/storage.rs | 10 +- crates/cast/tests/cli/main.rs | 42 ---- crates/forge/tests/cli/script.rs | 2 +- crates/script/src/simulate.rs | 10 +- crates/test-utils/src/util.rs | 5 +- crates/verify/src/etherscan/mod.rs | 9 +- crates/verify/src/provider.rs | 19 +- deny.toml | 3 +- 11 files changed, 158 insertions(+), 295 deletions(-) diff --git a/.github/workflows/nextest.yml b/.github/workflows/nextest.yml index 5f8a9561af7d4..c8c0e0961eb0c 100644 --- a/.github/workflows/nextest.yml +++ b/.github/workflows/nextest.yml @@ -68,11 +68,11 @@ jobs: with: bun-version: latest - name: Setup Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v4 with: python-version: 3.11 - name: Install Vyper - run: pip --version && pip install vyper==0.4.0 + run: pip install vyper==0.4.0 - name: Forge RPC cache uses: actions/cache@v3 diff --git a/Cargo.lock b/Cargo.lock index 58a3082ed6709..b4532ce77227a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -339,7 +339,7 @@ dependencies = [ "foldhash", "getrandom 0.2.15", "hashbrown 0.15.2", - "indexmap 2.8.0", + "indexmap 2.7.1", "itoa", "k256", "keccak-asm", @@ -435,7 +435,7 @@ checksum = "a40e1ef334153322fd878d07e86af7a529bcb86b2439525920a88eba87bcf943" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -708,7 +708,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -721,11 +721,11 @@ dependencies = [ "alloy-sol-macro-input", "const-hex", "heck", - "indexmap 2.8.0", + "indexmap 2.7.1", "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", "syn-solidity", "tiny-keccak", ] @@ -743,7 +743,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.100", + "syn 2.0.99", "syn-solidity", ] @@ -1289,7 +1289,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -1311,7 +1311,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -1322,7 +1322,7 @@ checksum = "d556ec1359574147ec0c4fc5eb525f3f23263a592b1a9c07e0a75b427de55c97" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -1375,7 +1375,7 @@ checksum = "e12882f59de5360c748c4cbf569a042d5fb0eb515f7bea9c1f470b47f6ffbd73" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -1565,9 +1565,9 @@ dependencies = [ [[package]] name = "aws-smithy-async" -version = "1.2.5" +version = "1.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e190749ea56f8c42bf15dd76c65e14f8f765233e6df9b0506d9d934ebef867c" +checksum = "fa59d1327d8b5053c54bf2eaae63bf629ba9e904434d0835a28ed3c0ed0a614e" dependencies = [ "futures-util", "pin-project-lite", @@ -1614,52 +1614,11 @@ dependencies = [ "tracing", ] -[[package]] -name = "aws-smithy-http" -version = "0.62.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5949124d11e538ca21142d1fba61ab0a2a2c1bc3ed323cdb3e4b878bfb83166" -dependencies = [ - "aws-smithy-runtime-api", - "aws-smithy-types", - "bytes", - "bytes-utils", - "futures-core", - "http 0.2.12", - "http 1.2.0", - "http-body 0.4.6", - "once_cell", - "percent-encoding", - "pin-project-lite", - "pin-utils", - "tracing", -] - -[[package]] -name = "aws-smithy-http-client" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0497ef5d53065b7cd6a35e9c1654bd1fefeae5c52900d91d1b188b0af0f29324" -dependencies = [ - "aws-smithy-async", - "aws-smithy-runtime-api", - "aws-smithy-types", - "h2 0.4.8", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.32", - "hyper-rustls 0.24.2", - "pin-project-lite", - "rustls 0.21.12", - "tokio", - "tracing", -] - [[package]] name = "aws-smithy-json" -version = "0.61.3" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92144e45819cae7dc62af23eac5a038a58aa544432d2102609654376a900bd07" +checksum = "623a51127f24c30776c8b374295f2df78d92517386f77ba30773f15a30ce1422" dependencies = [ "aws-smithy-types", ] @@ -1676,33 +1635,36 @@ dependencies = [ [[package]] name = "aws-smithy-runtime" -version = "1.8.0" +version = "1.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6328865e36c6fd970094ead6b05efd047d3a80ec5fc3be5e743910da9f2ebf8" +checksum = "d526a12d9ed61fadefda24abe2e682892ba288c2018bcb38b1b4c111d13f6d92" dependencies = [ "aws-smithy-async", - "aws-smithy-http 0.62.0", - "aws-smithy-http-client", + "aws-smithy-http 0.60.12", "aws-smithy-runtime-api", "aws-smithy-types", "bytes", "fastrand", + "h2 0.3.26", "http 0.2.12", - "http 1.2.0", "http-body 0.4.6", "http-body 1.0.1", + "httparse", + "hyper 0.14.32", + "hyper-rustls 0.24.2", "once_cell", "pin-project-lite", "pin-utils", + "rustls 0.21.12", "tokio", "tracing", ] [[package]] name = "aws-smithy-runtime-api" -version = "1.7.4" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3da37cf5d57011cb1753456518ec76e31691f1f474b73934a284eb2a1c76510f" +checksum = "92165296a47a812b267b4f41032ff8069ab7ff783696d217f0994a0d7ab585cd" dependencies = [ "aws-smithy-async", "aws-smithy-types", @@ -1717,9 +1679,9 @@ dependencies = [ [[package]] name = "aws-smithy-types" -version = "1.3.0" +version = "1.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836155caafba616c0ff9b07944324785de2ab016141c3550bd1c07882f8cee8f" +checksum = "c7b8a53819e42f10d0821f56da995e1470b199686a1809168db6ca485665f042" dependencies = [ "base64-simd", "bytes", @@ -1864,9 +1826,9 @@ dependencies = [ [[package]] name = "base64ct" -version = "1.7.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb97d56060ee67d285efb8001fec9d2a4c710c32efd2e14b5cbb5ba71930fc2d" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "bech32" @@ -1982,7 +1944,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -2271,9 +2233,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.32" +version = "4.5.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6088f3ae8c3608d19260cd7445411865a485688711b78b5be70d78cd96136f83" +checksum = "027bb0d98429ae334a8698531da7077bdf906419543a35a55c2cb1b66437d767" dependencies = [ "clap_builder", "clap_derive", @@ -2281,9 +2243,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.32" +version = "4.5.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22a7ef7f676155edfb82daa97f99441f3ebf4a58d5e32f295a56259f1b6facc8" +checksum = "5589e0cba072e0f3d23791efac0fd8627b49c829c196a492e88168e6a669d863" dependencies = [ "anstream", "anstyle", @@ -2315,14 +2277,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.32" +version = "4.5.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7" +checksum = "bf4ced95c6f4a675af3da73304b9ac4ed991640c36374e4b46795c49e17cf1ed" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -2578,9 +2540,9 @@ dependencies = [ [[package]] name = "convert_case" -version = "0.7.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb402b8d4c85569410425650ce3eddc7d698ed96d39a73f941b08fb63082f1e7" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" dependencies = [ "unicode-segmentation", ] @@ -2762,7 +2724,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -2773,7 +2735,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -2847,7 +2809,7 @@ checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -2868,7 +2830,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -2878,7 +2840,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -2905,9 +2867,10 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ + "convert_case", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", "unicode-xid", ] @@ -2917,10 +2880,9 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" dependencies = [ - "convert_case", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", "unicode-xid", ] @@ -3008,7 +2970,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -3033,7 +2995,7 @@ checksum = "8dc51d98e636f5e3b0759a39257458b22619cac7e96d932da6eeb052891bb67c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -3165,7 +3127,7 @@ checksum = "2f9ed6b3789237c8a0c1c505af1c7eb2c560df6186f01b098c3a1064ea532f38" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -3186,14 +3148,14 @@ checksum = "c7f84e12ccf0a7ddc17a6c41c93326024c42920d7ee630d04950e6926645c0fe" [[package]] name = "env_logger" -version = "0.11.7" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3716d7a920fb4fac5d84e9d4bce8ceb321e9414b4409da61b07b75c1e3d0697" +checksum = "dcaee3d8e3cfc3fd92428d477bc97fc29ec8716d180c0d74c643bb26166660e0" dependencies = [ "anstream", "anstyle", "env_filter", - "jiff 0.2.4", + "humantime", "log", ] @@ -3271,7 +3233,7 @@ dependencies = [ "ahash", "alloy-dyn-abi", "alloy-primitives", - "indexmap 2.8.0", + "indexmap 2.7.1", ] [[package]] @@ -3323,12 +3285,12 @@ dependencies = [ [[package]] name = "fd-lock" -version = "4.0.4" +version = "4.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce92ff622d6dadf7349484f42c93271a0d49b7cc4d466a936405bacbe10aa78" +checksum = "c44818c96aec5cadc9dacfb97bbcbcfc19a0de75b218412d56f57fbaab94e439" dependencies = [ "cfg-if", - "rustix 1.0.2", + "rustix 0.38.44", "windows-sys 0.59.0", ] @@ -3344,9 +3306,9 @@ dependencies = [ [[package]] name = "ff" -version = "0.13.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" dependencies = [ "rand_core 0.6.4", "subtle", @@ -3515,7 +3477,7 @@ name = "forge-doc" version = "1.0.0" dependencies = [ "alloy-primitives", - "derive_more 2.0.1", + "derive_more 1.0.0", "eyre", "forge-fmt", "foundry-common", @@ -3624,7 +3586,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -4055,7 +4017,7 @@ version = "1.0.0" dependencies = [ "alloy-primitives", "alloy-sol-types", - "derive_more 2.0.1", + "derive_more 1.0.0", "foundry-common-fmt", "foundry-macros", "foundry-test-utils", @@ -4202,7 +4164,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -4362,7 +4324,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -4540,7 +4502,7 @@ checksum = "c57c477b645ee248b173bb1176b52dd528872f12c50375801a58aaf5ae91113f" dependencies = [ "bstr", "itoa", - "jiff 0.1.29", + "jiff", "thiserror 2.0.12", ] @@ -4762,7 +4724,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.8.0", + "indexmap 2.7.1", "slab", "tokio", "tokio-util", @@ -4781,7 +4743,7 @@ dependencies = [ "futures-core", "futures-sink", "http 1.2.0", - "indexmap 2.8.0", + "indexmap 2.7.1", "slab", "tokio", "tokio-util", @@ -4919,7 +4881,7 @@ dependencies = [ "markup5ever", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -5262,7 +5224,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -5344,7 +5306,7 @@ checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -5372,9 +5334,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.8.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3954d50fe15b02142bf25d3b8bdadb634ec3948f103d04ffe3031bc8fe9d7058" +checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" dependencies = [ "arbitrary", "equivalent", @@ -5462,7 +5424,7 @@ dependencies = [ "indoc", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -5559,30 +5521,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "jiff" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d699bc6dfc879fb1bf9bdff0d4c56f0884fc6f0d0eb0fba397a6d00cd9a6b85e" -dependencies = [ - "jiff-static", - "log", - "portable-atomic", - "portable-atomic-util", - "serde", -] - -[[package]] -name = "jiff-static" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d16e75759ee0aa64c57a56acbf43916987b20c77373cb7e808979e02b93c9f9" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - [[package]] name = "jiff-tzdb" version = "0.1.3" @@ -5912,9 +5850,9 @@ dependencies = [ [[package]] name = "mdbook" -version = "0.4.47" +version = "0.4.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e1a8fe3a4a01f28dab245c474cb7b95ccb4d3d2f17a5419a3d949f474c45e84" +checksum = "85c54109598152e19add1933b223b1913bcd16e27cbd7c2783269fe2f9a6cbdc" dependencies = [ "ammonia", "anyhow", @@ -5995,7 +5933,7 @@ checksum = "bf45bf44ab49be92fd1227a3be6fc6f617f1a337c06af54981048574d8783147" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -6073,7 +6011,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -6323,7 +6261,7 @@ checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -6365,9 +6303,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.21.0" +version = "1.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde51589ab56b20a6f686b2c68f7a0bd6add753d697abf720d63f8db3ab7b1ad" +checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" [[package]] name = "op-alloy-consensus" @@ -6482,7 +6420,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -6565,7 +6503,7 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -6624,7 +6562,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -6645,7 +6583,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.8.0", + "indexmap 2.7.1", ] [[package]] @@ -6698,7 +6636,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -6747,7 +6685,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -6801,11 +6739,11 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.21" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" dependencies = [ - "zerocopy 0.8.23", + "zerocopy 0.7.35", ] [[package]] @@ -6847,7 +6785,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1ccf34da56fc294e7d4ccf69a85992b7dfb826b7cf57bac6a70bba3494cc08a" dependencies = [ "proc-macro2", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -6922,7 +6860,7 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -6942,7 +6880,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", "version_check", "yansi", ] @@ -6954,7 +6892,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d35f4dc9988d1326b065b4def5e950c3ed727aa03e3151b86cc9e2aec6b03f54" dependencies = [ "futures", - "indexmap 2.8.0", + "indexmap 2.7.1", "nix 0.29.0", "tokio", "tracing", @@ -7010,7 +6948,7 @@ checksum = "4ee1c9ac207483d5e7db4940700de86a9aae46ef90c48b57f99fe7edb8345e49" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -7033,7 +6971,7 @@ dependencies = [ "itertools 0.14.0", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -7096,7 +7034,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ed1a693391a16317257103ad06a88c6529ac640846021da7c435a06fffdacd7" dependencies = [ "chrono", - "indexmap 2.8.0", + "indexmap 2.7.1", "newtype-uuid", "quick-xml 0.37.2", "strip-ansi-escapes", @@ -7449,9 +7387,9 @@ dependencies = [ [[package]] name = "revm" -version = "19.6.0" +version = "19.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b906766b7ba049b515848952b5ae74f363d456e98de2021048a513e442b4f42" +checksum = "dfc5bef3c95fadf3b6a24a253600348380c169ef285f9780a793bb7090c8990d" dependencies = [ "auto_impl", "cfg-if", @@ -7701,9 +7639,9 @@ dependencies = [ [[package]] name = "rustix" -version = "1.0.2" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7178faa4b75a30e269c71e61c353ce2748cf3d76f0c44c393f4e60abf49b825" +checksum = "dade4812df5c384711475be5fcd8c162555352945401aed22a35bffeab61f657" dependencies = [ "bitflags 2.9.0", "errno", @@ -7924,7 +7862,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -7963,9 +7901,9 @@ dependencies = [ [[package]] name = "sdd" -version = "3.0.8" +version = "3.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "584e070911c7017da6cb2eb0788d09f43d789029b5877d3e5ecc8acf86ceee21" +checksum = "b07779b9b918cc05650cb30f404d4d7835d26df37c235eded8a6832e2fb82cca" [[package]] name = "sec1" @@ -8085,22 +8023,22 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.219" +version = "1.0.218" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.219" +version = "1.0.218" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -8111,7 +8049,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -8120,7 +8058,7 @@ version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" dependencies = [ - "indexmap 2.8.0", + "indexmap 2.7.1", "itoa", "memchr", "ryu", @@ -8155,7 +8093,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -8189,7 +8127,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.8.0", + "indexmap 2.7.1", "serde", "serde_derive", "serde_json", @@ -8206,7 +8144,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -8241,7 +8179,7 @@ checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -8507,7 +8445,7 @@ checksum = "71d07263243b313296eca18f18eda3a190902dc3284bf67ceff29b8b54dac3e6" dependencies = [ "bumpalo", "index_vec", - "indexmap 2.8.0", + "indexmap 2.7.1", "parking_lot", "rayon", "rustc-hash", @@ -8550,7 +8488,7 @@ checksum = "970d7c774741f786d62cab78290e47d845b0b9c0c9d094a1642aced1d7946036" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -8722,7 +8660,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -8735,7 +8673,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -8803,9 +8741,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.100" +version = "2.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" +checksum = "e02e925281e18ffd9d640e234264753c43edc62d64b2d4cf898f1bc5e75f3fc2" dependencies = [ "proc-macro2", "quote", @@ -8821,7 +8759,7 @@ dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -8841,7 +8779,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -8860,7 +8798,7 @@ dependencies = [ "fastrand", "getrandom 0.3.1", "once_cell", - "rustix 1.0.2", + "rustix 1.0.1", "windows-sys 0.59.0", ] @@ -8892,7 +8830,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45c6481c4829e4cc63825e62c49186a34538b7b2750b73b266581ffb612fb5ed" dependencies = [ - "rustix 1.0.2", + "rustix 1.0.1", "windows-sys 0.59.0", ] @@ -8951,7 +8889,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -8962,7 +8900,7 @@ checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -9097,7 +9035,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -9200,7 +9138,7 @@ version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148" dependencies = [ - "indexmap 2.8.0", + "indexmap 2.7.1", "serde", "serde_spanned", "toml_datetime", @@ -9222,7 +9160,7 @@ version = "0.22.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" dependencies = [ - "indexmap 2.8.0", + "indexmap 2.7.1", "serde", "serde_spanned", "toml_datetime", @@ -9373,7 +9311,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -9810,7 +9748,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", "wasm-bindgen-shared", ] @@ -9845,7 +9783,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -10090,7 +10028,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -10101,7 +10039,7 @@ checksum = "83577b051e2f49a058c308f17f273b570a6a758386fc291b5f6a934dd84e48c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -10112,7 +10050,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -10123,7 +10061,7 @@ checksum = "cb26fd936d991781ea39e87c3a27285081e3c0da5ca0fcbc02d368cc6f52ff01" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -10500,7 +10438,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", "synstructure", ] @@ -10510,6 +10448,7 @@ version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ + "byteorder", "zerocopy-derive 0.7.35", ] @@ -10530,7 +10469,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -10541,7 +10480,7 @@ checksum = "6352c01d0edd5db859a63e2605f4ea3183ddbd15e2c4a9e7d32184df75e4f154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -10561,7 +10500,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", "synstructure", ] @@ -10582,7 +10521,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -10604,7 +10543,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.99", ] [[package]] @@ -10619,7 +10558,7 @@ dependencies = [ "crossbeam-utils", "displaydoc", "flate2", - "indexmap 2.8.0", + "indexmap 2.7.1", "memchr", "thiserror 2.0.12", "zopfli", diff --git a/Cargo.toml b/Cargo.toml index b55f708db90cc..f6cb1e06f6c75 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -255,7 +255,7 @@ proc-macro2 = "1.0" quote = "1.0" syn = "2.0" async-trait = "0.1" -derive_more = { version = "2.0", features = ["full"] } +derive_more = { version = "1.0", features = ["full"] } thiserror = "2" # bench diff --git a/crates/cast/bin/cmd/storage.rs b/crates/cast/bin/cmd/storage.rs index c51511c423487..c7a90ad2f06b5 100644 --- a/crates/cast/bin/cmd/storage.rs +++ b/crates/cast/bin/cmd/storage.rs @@ -51,10 +51,6 @@ pub struct StorageArgs { #[arg(value_parser = parse_slot)] slot: Option, - /// The known proxy address. If provided, the storage layout is retrieved from this address. - #[arg(long,value_parser = NameOrAddress::from_str)] - proxy: Option, - /// The block height to query at. /// /// Can also be the tags earliest, finalized, safe, latest, or pending. @@ -138,11 +134,7 @@ impl StorageArgs { let chain = utils::get_chain(config.chain, &provider).await?; let api_key = config.get_etherscan_api_key(Some(chain)).unwrap_or_default(); let client = Client::new(chain, api_key)?; - let source = if let Some(proxy) = self.proxy { - find_source(client, proxy.resolve(&provider).await?).await? - } else { - find_source(client, address).await? - }; + let source = find_source(client, address).await?; let metadata = source.items.first().unwrap(); if metadata.is_vyper() { eyre::bail!("Contract at provided address is not a valid Solidity contract") diff --git a/crates/cast/tests/cli/main.rs b/crates/cast/tests/cli/main.rs index 2d1ad75854999..fedcb7d7d2a70 100644 --- a/crates/cast/tests/cli/main.rs +++ b/crates/cast/tests/cli/main.rs @@ -1295,48 +1295,6 @@ casttest!(storage_layout_complex, |_prj, cmd| { ╰-------------------------------+--------------------------------------------------------------------+------+--------+-------+--------------------------------------------------+--------------------------------------------------------------------+---------------------------------╯ -"#]]); -}); - -casttest!(storage_layout_complex_proxy, |_prj, cmd| { - cmd.args([ - "storage", - "--rpc-url", - next_rpc_endpoint(NamedChain::Sepolia).as_str(), - "--block", - "7857852", - "--etherscan-api-key", - next_mainnet_etherscan_api_key().as_str(), - "0xE2588A9CAb7Ea877206E35f615a39f84a64A7A3b", - "--proxy", - "0x29fcb43b46531bca003ddc8fcb67ffe91900c762" - ]) - .assert_success() - .stdout_eq(str![[r#" - -╭----------------------------+-------------------------------------------------+------+--------+-------+--------------------------------------------------+--------------------------------------------------------------------+-----------------------------╮ -| Name | Type | Slot | Offset | Bytes | Value | Hex Value | Contract | -+============================================================================================================================================================================================================================================================+ -| singleton | address | 0 | 0 | 20 | 239704109775411986678417050956533140837380441954 | 0x00000000000000000000000029fcb43b46531bca003ddc8fcb67ffe91900c762 | contracts/SafeL2.sol:SafeL2 | -|----------------------------+-------------------------------------------------+------+--------+-------+--------------------------------------------------+--------------------------------------------------------------------+-----------------------------| -| modules | mapping(address => address) | 1 | 0 | 32 | 0 | 0x0000000000000000000000000000000000000000000000000000000000000000 | contracts/SafeL2.sol:SafeL2 | -|----------------------------+-------------------------------------------------+------+--------+-------+--------------------------------------------------+--------------------------------------------------------------------+-----------------------------| -| owners | mapping(address => address) | 2 | 0 | 32 | 0 | 0x0000000000000000000000000000000000000000000000000000000000000000 | contracts/SafeL2.sol:SafeL2 | -|----------------------------+-------------------------------------------------+------+--------+-------+--------------------------------------------------+--------------------------------------------------------------------+-----------------------------| -| ownerCount | uint256 | 3 | 0 | 32 | 1 | 0x0000000000000000000000000000000000000000000000000000000000000001 | contracts/SafeL2.sol:SafeL2 | -|----------------------------+-------------------------------------------------+------+--------+-------+--------------------------------------------------+--------------------------------------------------------------------+-----------------------------| -| threshold | uint256 | 4 | 0 | 32 | 1 | 0x0000000000000000000000000000000000000000000000000000000000000001 | contracts/SafeL2.sol:SafeL2 | -|----------------------------+-------------------------------------------------+------+--------+-------+--------------------------------------------------+--------------------------------------------------------------------+-----------------------------| -| nonce | uint256 | 5 | 0 | 32 | 0 | 0x0000000000000000000000000000000000000000000000000000000000000000 | contracts/SafeL2.sol:SafeL2 | -|----------------------------+-------------------------------------------------+------+--------+-------+--------------------------------------------------+--------------------------------------------------------------------+-----------------------------| -| _deprecatedDomainSeparator | bytes32 | 6 | 0 | 32 | 0 | 0x0000000000000000000000000000000000000000000000000000000000000000 | contracts/SafeL2.sol:SafeL2 | -|----------------------------+-------------------------------------------------+------+--------+-------+--------------------------------------------------+--------------------------------------------------------------------+-----------------------------| -| signedMessages | mapping(bytes32 => uint256) | 7 | 0 | 32 | 0 | 0x0000000000000000000000000000000000000000000000000000000000000000 | contracts/SafeL2.sol:SafeL2 | -|----------------------------+-------------------------------------------------+------+--------+-------+--------------------------------------------------+--------------------------------------------------------------------+-----------------------------| -| approvedHashes | mapping(address => mapping(bytes32 => uint256)) | 8 | 0 | 32 | 0 | 0x0000000000000000000000000000000000000000000000000000000000000000 | contracts/SafeL2.sol:SafeL2 | -╰----------------------------+-------------------------------------------------+------+--------+-------+--------------------------------------------------+--------------------------------------------------------------------+-----------------------------╯ - - "#]]); }); diff --git a/crates/forge/tests/cli/script.rs b/crates/forge/tests/cli/script.rs index 465d3db337590..aaf0658c65ac3 100644 --- a/crates/forge/tests/cli/script.rs +++ b/crates/forge/tests/cli/script.rs @@ -1953,7 +1953,7 @@ contract SimpleScript is Script { .assert_success() .stdout_eq(str![[r#" {"logs":[],"returns":{"success":{"internal_type":"bool","value":"true"}},"success":true,"raw_logs":[],"traces":[["Deployment",{"arena":[{"parent":null,"children":[],"idx":0,"trace":{"depth":0,"success":true,"caller":"0x1804c8ab1f12e6bbf3894d4083f33e07309d1f38","address":"0x5b73c5498c1e3b4dba84de0f1833c4a029d90519","maybe_precompile":false,"selfdestruct_address":null,"selfdestruct_refund_target":null,"selfdestruct_transferred_value":null,"kind":"CREATE","value":"0x0","data":"[..]","output":"[..]","gas_used":"{...}","gas_limit":"{...}","status":"Return","steps":[],"decoded":{"label":null,"return_data":null,"call_data":null}},"logs":[],"ordering":[]}]}],["Execution",{"arena":[{"parent":null,"children":[1,2],"idx":0,"trace":{"depth":0,"success":true,"caller":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","address":"0x5b73c5498c1e3b4dba84de0f1833c4a029d90519","maybe_precompile":null,"selfdestruct_address":null,"selfdestruct_refund_target":null,"selfdestruct_transferred_value":null,"kind":"CALL","value":"0x0","data":"0xc0406226","output":"0x0000000000000000000000000000000000000000000000000000000000000001","gas_used":"{...}","gas_limit":1073720760,"status":"Return","steps":[],"decoded":{"label":null,"return_data":null,"call_data":null}},"logs":[],"ordering":[{"Call":0},{"Call":1}]},{"parent":0,"children":[],"idx":1,"trace":{"depth":1,"success":true,"caller":"0x5b73c5498c1e3b4dba84de0f1833c4a029d90519","address":"0x7109709ecfa91a80626ff3989d68f67f5b1dd12d","maybe_precompile":null,"selfdestruct_address":null,"selfdestruct_refund_target":null,"selfdestruct_transferred_value":null,"kind":"CALL","value":"0x0","data":"0x7fb5297f","output":"0x","gas_used":"{...}","gas_limit":1056940994,"status":"Return","steps":[],"decoded":{"label":null,"return_data":null,"call_data":null}},"logs":[],"ordering":[]},{"parent":0,"children":[],"idx":2,"trace":{"depth":1,"success":true,"caller":"0x5b73c5498c1e3b4dba84de0f1833c4a029d90519","address":"0x0000000000000000000000000000000000000000","maybe_precompile":null,"selfdestruct_address":null,"selfdestruct_refund_target":null,"selfdestruct_transferred_value":null,"kind":"CALL","value":"0x0","data":"0x","output":"0x","gas_used":"{...}","gas_limit":1056940645,"status":"Stop","steps":[],"decoded":{"label":null,"return_data":null,"call_data":null}},"logs":[],"ordering":[]}]}]],"gas_used":"{...}","labeled_addresses":{},"returned":"0x0000000000000000000000000000000000000000000000000000000000000001","address":null} -{"chain":31337,"estimated_gas_price":"{...}","estimated_total_gas_used":"{...}","estimated_amount_required":"{...}","token_symbol":"ETH"} +{"chain":31337,"estimated_gas_price":"{...}","estimated_total_gas_used":"{...}","estimated_amount_required":"{...}"} {"chain":"anvil-hardhat","status":"success","tx_hash":"0x4f78afe915fceb282c7625a68eb350bc0bf78acb59ad893e5c62b710a37f3156","contract_address":null,"block_number":1,"gas_used":"{...}","gas_price":"{...}"} {"status":"success","transactions":"[..]/broadcast/Foo.sol/31337/run-latest.json","sensitive":"[..]/cache/Foo.sol/31337/run-latest.json"} diff --git a/crates/script/src/simulate.rs b/crates/script/src/simulate.rs index a58b1058ebc2e..cf6aeb349436b 100644 --- a/crates/script/src/simulate.rs +++ b/crates/script/src/simulate.rs @@ -9,7 +9,6 @@ use crate::{ sequence::get_commit_hash, ScriptArgs, ScriptConfig, ScriptResult, }; -use alloy_chains::NamedChain; use alloy_network::TransactionBuilder; use alloy_primitives::{map::HashMap, utils::format_units, Address, Bytes, TxKind, U256}; use dialoguer::Confirm; @@ -347,12 +346,6 @@ impl FilledTransactionsState { for (rpc, total_gas) in total_gas_per_rpc { let provider_info = manager.get(&rpc).expect("provider is set."); - // Get the native token symbol for the chain using NamedChain - let token_symbol = NamedChain::try_from(provider_info.chain) - .unwrap_or_default() - .native_currency_symbol() - .unwrap_or("ETH"); - // We don't store it in the transactions, since we want the most updated value. // Right before broadcasting. let per_gas = if let Some(gas_price) = self.args.with_gas_price { @@ -376,7 +369,7 @@ impl FilledTransactionsState { sh_println!("\nEstimated gas price: {} gwei", estimated_gas_price)?; sh_println!("\nEstimated total gas used for script: {total_gas}")?; - sh_println!("\nEstimated amount required: {estimated_amount} {token_symbol}")?; + sh_println!("\nEstimated amount required: {estimated_amount} ETH",)?; sh_println!("\n==========================")?; } else { sh_println!( @@ -386,7 +379,6 @@ impl FilledTransactionsState { "estimated_gas_price": estimated_gas_price, "estimated_total_gas_used": total_gas, "estimated_amount_required": estimated_amount, - "token_symbol": token_symbol, }) )?; } diff --git a/crates/test-utils/src/util.rs b/crates/test-utils/src/util.rs index 3c2b0546f7061..123bda33dbb9d 100644 --- a/crates/test-utils/src/util.rs +++ b/crates/test-utils/src/util.rs @@ -1019,10 +1019,7 @@ fn test_redactions() -> snapbox::Redactions { ("[SAVED_SENSITIVE_VALUES]", r"Sensitive values saved to: .*\.json"), ("[ESTIMATED_GAS_PRICE]", r"Estimated gas price:\s*(\d+(\.\d+)?)\s*gwei"), ("[ESTIMATED_TOTAL_GAS_USED]", r"Estimated total gas used for script: \d+"), - ( - "[ESTIMATED_AMOUNT_REQUIRED]", - r"Estimated amount required:\s*(\d+(\.\d+)?)\s*[A-Z]{3}", - ), + ("[ESTIMATED_AMOUNT_REQUIRED]", r"Estimated amount required:\s*(\d+(\.\d+)?)\s*ETH"), ]; for (placeholder, re) in redactions { r.insert(placeholder, Regex::new(re).expect(re)).expect(re); diff --git a/crates/verify/src/etherscan/mod.rs b/crates/verify/src/etherscan/mod.rs index e61d5e1b07f5c..eece0c928064d 100644 --- a/crates/verify/src/etherscan/mod.rs +++ b/crates/verify/src/etherscan/mod.rs @@ -278,13 +278,8 @@ impl EtherscanVerificationProvider { builder = if let Some(api_url) = api_url { // we don't want any trailing slashes because this can cause cloudflare issues: let api_url = api_url.trim_end_matches('/'); - - // Verifier is etherscan if explicitly set or if no verifier set (default sourcify) but - // API key passed. - let is_etherscan = verifier_type.is_etherscan() || - (verifier_type.is_sourcify() && etherscan_key.is_some()); - let base_url = if !is_etherscan { - // If verifier is not Etherscan then set base url as api url without /api suffix. + let base_url = if *verifier_type != VerificationProviderType::Etherscan { + // If verifier is not Etherscan then set base url as api url without trialing /api. api_url.strip_prefix("/api").unwrap_or(api_url) } else { base_url.unwrap_or(api_url) diff --git a/crates/verify/src/provider.rs b/crates/verify/src/provider.rs index 01a06332a36ce..07f1e09ea6aa3 100644 --- a/crates/verify/src/provider.rs +++ b/crates/verify/src/provider.rs @@ -170,9 +170,8 @@ pub enum VerificationProviderType { impl VerificationProviderType { /// Returns the corresponding `VerificationProvider` for the key pub fn client(&self, key: Option<&str>) -> Result> { - let has_key = key.as_ref().is_some_and(|k| !k.is_empty()); - // 1. If no verifier or `--verifier sourcify` is set and no API key provided, use Sourcify. - if !has_key && self.is_sourcify() { + // 1. If `--verifier sourcify` is set, always use Sourcify. + if matches!(self, Self::Sourcify) { sh_println!( "Attempting to verify on Sourcify. Pass the --etherscan-api-key to verify on Etherscan, \ or use the --verifier flag to verify on another provider." @@ -181,8 +180,8 @@ impl VerificationProviderType { } // 2. If `--verifier etherscan` is explicitly set, enforce the API key requirement. - if self.is_etherscan() { - if !has_key { + if matches!(self, Self::Etherscan) { + if key.as_ref().is_none_or(|key| key.is_empty()) { eyre::bail!("ETHERSCAN_API_KEY must be set to use Etherscan as a verifier") } return Ok(Box::::default()); @@ -195,19 +194,11 @@ impl VerificationProviderType { } // 4. If no `--verifier` is specified but `ETHERSCAN_API_KEY` is set, default to Etherscan. - if has_key { + if key.as_ref().is_some_and(|k| !k.is_empty()) { return Ok(Box::::default()); } // 5. If no valid provider is specified, bail. eyre::bail!("No valid verification provider specified. Pass the --verifier flag to specify a provider or set the ETHERSCAN_API_KEY environment variable to use Etherscan as a verifier.") } - - pub fn is_sourcify(&self) -> bool { - matches!(self, Self::Sourcify) - } - - pub fn is_etherscan(&self) -> bool { - matches!(self, Self::Etherscan) - } } diff --git a/deny.toml b/deny.toml index 33c5a4233e55d..ac92742909a18 100644 --- a/deny.toml +++ b/deny.toml @@ -11,8 +11,6 @@ ignore = [ "RUSTSEC-2024-0436", # https://rustsec.org/advisories/RUSTSEC-2024-0437 protobuf! Crash due to uncontrolled recursion in protobuf crate. "RUSTSEC-2024-0437", - # humantime is unmaintained - "RUSTSEC-2025-0014", ] # This section is considered when running `cargo deny check bans`. @@ -49,6 +47,7 @@ allow = [ "BSD-3-Clause", "ISC", "Unicode-3.0", + "OpenSSL", "Unlicense", "WTFPL", "BSL-1.0", From 90896e02a97e4846707f923d85f0e6d20e113792 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Sun, 27 Apr 2025 05:39:27 +0700 Subject: [PATCH 027/232] Add .circleci/config.yml --- .circleci/config.yml | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 .circleci/config.yml diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000000000..62291703e26a7 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,31 @@ +# Use the latest 2.1 version of CircleCI pipeline process engine. +# See: https://circleci.com/docs/configuration-reference +version: 2.1 + +# Define a job to be invoked later in a workflow. +# See: https://circleci.com/docs/jobs-steps/#jobs-overview & https://circleci.com/docs/configuration-reference/#jobs +jobs: + say-hello: + # Specify the execution environment. You can specify an image from Docker Hub or use one of our convenience images from CircleCI's Developer Hub. + # See: https://circleci.com/docs/executor-intro/ & https://circleci.com/docs/configuration-reference/#executor-job + docker: + # Specify the version you desire here + # See: https://circleci.com/developer/images/image/cimg/base + - image: cimg/base:current + + # Add steps to the job + # See: https://circleci.com/docs/jobs-steps/#steps-overview & https://circleci.com/docs/configuration-reference/#steps + steps: + # Checkout the code as the first step. + - checkout + - run: + name: "Say hello" + command: "echo Hello, World!" + +# Orchestrate jobs using workflows +# See: https://circleci.com/docs/workflows/ & https://circleci.com/docs/configuration-reference/#workflows +workflows: + say-hello-workflow: # This is the name of the workflow, feel free to change it to better match your workflow. + # Inside the workflow, you define the jobs you want to run. + jobs: + - say-hello \ No newline at end of file From 9b9f087ed2f71981b133d29e06fe3f8e95397ff0 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Sun, 27 Apr 2025 09:23:52 +0700 Subject: [PATCH 028/232] Updated config.yml --- .circleci/config.yml | 120 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 99 insertions(+), 21 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 62291703e26a7..5121ad4351f4b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,31 +1,109 @@ -# Use the latest 2.1 version of CircleCI pipeline process engine. -# See: https://circleci.com/docs/configuration-reference version: 2.1 - -# Define a job to be invoked later in a workflow. -# See: https://circleci.com/docs/jobs-steps/#jobs-overview & https://circleci.com/docs/configuration-reference/#jobs jobs: - say-hello: - # Specify the execution environment. You can specify an image from Docker Hub or use one of our convenience images from CircleCI's Developer Hub. - # See: https://circleci.com/docs/executor-intro/ & https://circleci.com/docs/configuration-reference/#executor-job + build: docker: - # Specify the version you desire here - # See: https://circleci.com/developer/images/image/cimg/base - - image: cimg/base:current + - image: ubuntu:23.04 + + - image: mongo:6.0.14 + command: [mongod, --smallfiles] + + - image: postgres:14.12 + # some containers require setting environment variables + environment: + POSTGRES_USER: user + + - image: redis@sha256:54057dd7e125ca41afe526a877e8bd35ec2cdd33b9217e022ed37bdcf7d09673 + + - image: rabbitmq:3.12.12 + + environment: + TEST_REPORTS: /tmp/test-reports + + working_directory: ~/my-project - # Add steps to the job - # See: https://circleci.com/docs/jobs-steps/#steps-overview & https://circleci.com/docs/configuration-reference/#steps steps: - # Checkout the code as the first step. - checkout + + - run: + command: echo 127.0.0.1 devhost | sudo tee -a /etc/hosts + + # Create Postgres users and database + # Note the YAML heredoc '|' for nicer formatting + - run: | + sudo -u root createuser -h localhost --superuser ubuntu && + sudo createdb -h localhost test_db + + - restore_cache: + keys: + - v1-my-project-{{ checksum "project.clj" }} + - v1-my-project- + + - run: + environment: + SSH_TARGET: "localhost" + TEST_ENV: "linux" + command: | + set -xu + mkdir -p ${TEST_REPORTS} + run-tests.sh + cp out/tests/*.xml ${TEST_REPORTS} + + - run: | + set -xu + mkdir -p /tmp/artifacts + create_jars.sh << pipeline.number >> + cp *.jar /tmp/artifacts + + - save_cache: + key: v1-my-project-{{ checksum "project.clj" }} + paths: + - ~/.m2 + + # Save artifacts + - store_artifacts: + path: /tmp/artifacts + destination: build + + # Upload test results + - store_test_results: + path: /tmp/test-reports + + deploy-stage: + docker: + - image: ubuntu:23.04 + working_directory: /tmp/my-project + steps: + - run: + name: Deploy if tests pass and branch is Staging + command: ansible-playbook site.yml -i staging + + deploy-prod: + docker: + - image: ubuntu:23.04 + working_directory: /tmp/my-project + steps: - run: - name: "Say hello" - command: "echo Hello, World!" + name: Deploy if tests pass and branch is Main + command: ansible-playbook site.yml -i production -# Orchestrate jobs using workflows -# See: https://circleci.com/docs/workflows/ & https://circleci.com/docs/configuration-reference/#workflows workflows: - say-hello-workflow: # This is the name of the workflow, feel free to change it to better match your workflow. - # Inside the workflow, you define the jobs you want to run. + build-deploy: jobs: - - say-hello \ No newline at end of file + - build: + filters: + branches: + ignore: + - develop + - /feature-.*/ + - deploy-stage: + requires: + - build + filters: + branches: + only: staging + - deploy-prod: + requires: + - build + filters: + branches: + only: main \ No newline at end of file From ad4415ad276513863df50b5e4e8bace30bfc05f0 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Sun, 27 Apr 2025 09:28:14 +0700 Subject: [PATCH 029/232] Updated config.yml --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 5121ad4351f4b..29513b62d13e3 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,7 +5,7 @@ jobs: - image: ubuntu:23.04 - image: mongo:6.0.14 - command: [mongod, --smallfiles] + command: [mongod --dbpath /path/to/data] - image: postgres:14.12 # some containers require setting environment variables From 37b29ad897addfcbd4f01c01bec55283a27bd947 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Sun, 27 Apr 2025 09:31:08 +0700 Subject: [PATCH 030/232] Updated config.yml --- .circleci/config.yml | 120 ++++++++----------------------------------- 1 file changed, 21 insertions(+), 99 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 29513b62d13e3..62291703e26a7 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,109 +1,31 @@ +# Use the latest 2.1 version of CircleCI pipeline process engine. +# See: https://circleci.com/docs/configuration-reference version: 2.1 + +# Define a job to be invoked later in a workflow. +# See: https://circleci.com/docs/jobs-steps/#jobs-overview & https://circleci.com/docs/configuration-reference/#jobs jobs: - build: + say-hello: + # Specify the execution environment. You can specify an image from Docker Hub or use one of our convenience images from CircleCI's Developer Hub. + # See: https://circleci.com/docs/executor-intro/ & https://circleci.com/docs/configuration-reference/#executor-job docker: - - image: ubuntu:23.04 - - - image: mongo:6.0.14 - command: [mongod --dbpath /path/to/data] - - - image: postgres:14.12 - # some containers require setting environment variables - environment: - POSTGRES_USER: user - - - image: redis@sha256:54057dd7e125ca41afe526a877e8bd35ec2cdd33b9217e022ed37bdcf7d09673 - - - image: rabbitmq:3.12.12 - - environment: - TEST_REPORTS: /tmp/test-reports - - working_directory: ~/my-project + # Specify the version you desire here + # See: https://circleci.com/developer/images/image/cimg/base + - image: cimg/base:current + # Add steps to the job + # See: https://circleci.com/docs/jobs-steps/#steps-overview & https://circleci.com/docs/configuration-reference/#steps steps: + # Checkout the code as the first step. - checkout - - - run: - command: echo 127.0.0.1 devhost | sudo tee -a /etc/hosts - - # Create Postgres users and database - # Note the YAML heredoc '|' for nicer formatting - - run: | - sudo -u root createuser -h localhost --superuser ubuntu && - sudo createdb -h localhost test_db - - - restore_cache: - keys: - - v1-my-project-{{ checksum "project.clj" }} - - v1-my-project- - - - run: - environment: - SSH_TARGET: "localhost" - TEST_ENV: "linux" - command: | - set -xu - mkdir -p ${TEST_REPORTS} - run-tests.sh - cp out/tests/*.xml ${TEST_REPORTS} - - - run: | - set -xu - mkdir -p /tmp/artifacts - create_jars.sh << pipeline.number >> - cp *.jar /tmp/artifacts - - - save_cache: - key: v1-my-project-{{ checksum "project.clj" }} - paths: - - ~/.m2 - - # Save artifacts - - store_artifacts: - path: /tmp/artifacts - destination: build - - # Upload test results - - store_test_results: - path: /tmp/test-reports - - deploy-stage: - docker: - - image: ubuntu:23.04 - working_directory: /tmp/my-project - steps: - - run: - name: Deploy if tests pass and branch is Staging - command: ansible-playbook site.yml -i staging - - deploy-prod: - docker: - - image: ubuntu:23.04 - working_directory: /tmp/my-project - steps: - run: - name: Deploy if tests pass and branch is Main - command: ansible-playbook site.yml -i production + name: "Say hello" + command: "echo Hello, World!" +# Orchestrate jobs using workflows +# See: https://circleci.com/docs/workflows/ & https://circleci.com/docs/configuration-reference/#workflows workflows: - build-deploy: + say-hello-workflow: # This is the name of the workflow, feel free to change it to better match your workflow. + # Inside the workflow, you define the jobs you want to run. jobs: - - build: - filters: - branches: - ignore: - - develop - - /feature-.*/ - - deploy-stage: - requires: - - build - filters: - branches: - only: staging - - deploy-prod: - requires: - - build - filters: - branches: - only: main \ No newline at end of file + - say-hello \ No newline at end of file From 975ca47b8c27518fe24014a3455a46ff950b1e94 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Fri, 9 May 2025 22:38:42 +0700 Subject: [PATCH 031/232] Create jekyll.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .github/workflows/jekyll.yml | 65 ++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 .github/workflows/jekyll.yml diff --git a/.github/workflows/jekyll.yml b/.github/workflows/jekyll.yml new file mode 100644 index 0000000000000..501686bcc9563 --- /dev/null +++ b/.github/workflows/jekyll.yml @@ -0,0 +1,65 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +# Sample workflow for building and deploying a Jekyll site to GitHub Pages +name: Deploy Jekyll site to Pages + +on: + # Runs on pushes targeting the default branch + push: + branches: ["master"] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages +permissions: + contents: read + pages: write + id-token: write + +# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. +# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. +concurrency: + group: "pages" + cancel-in-progress: false + +jobs: + # Build job + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Setup Ruby + # https://github.com/ruby/setup-ruby/releases/tag/v1.207.0 + uses: ruby/setup-ruby@4a9ddd6f338a97768b8006bf671dfbad383215f4 + with: + ruby-version: '3.1' # Not needed with a .ruby-version file + bundler-cache: true # runs 'bundle install' and caches installed gems automatically + cache-version: 0 # Increment this number if you need to re-download cached gems + - name: Setup Pages + id: pages + uses: actions/configure-pages@v5 + - name: Build with Jekyll + # Outputs to the './_site' directory by default + run: bundle exec jekyll build --baseurl "${{ steps.pages.outputs.base_path }}" + env: + JEKYLL_ENV: production + - name: Upload artifact + # Automatically uploads an artifact from the './_site' directory by default + uses: actions/upload-pages-artifact@v3 + + # Deployment job + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + needs: build + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 From 3f90e930ddf16aa53b2fe971d7afbf55e982be7f Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Fri, 9 May 2025 23:02:24 +0700 Subject: [PATCH 032/232] Create docker-image.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .github/workflows/docker-image.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 .github/workflows/docker-image.yml diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml new file mode 100644 index 0000000000000..793d8e0e39e39 --- /dev/null +++ b/.github/workflows/docker-image.yml @@ -0,0 +1,18 @@ +name: Docker Image CI + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + +jobs: + + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Build the Docker image + run: docker build . --file Dockerfile --tag my-image-name:$(date +%s) From 79528db656d98ec2c59e33f37e2e3e5980e21189 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Fri, 9 May 2025 23:18:47 +0700 Subject: [PATCH 033/232] Potential fix for code scanning alert no. 58: Workflow does not contain permissions Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .github/workflows/docker-image.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index 793d8e0e39e39..fe65b8b969f4d 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -6,6 +6,9 @@ on: pull_request: branches: [ "master" ] +permissions: + contents: read + jobs: build: From 4d200a767a10e925ceb4185fa4765d102984173e Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Fri, 9 May 2025 23:19:20 +0700 Subject: [PATCH 034/232] Update .github/workflows/docker-image.yml Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .github/workflows/docker-image.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index fe65b8b969f4d..b37794b4a7f85 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -17,5 +17,5 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Build the Docker image - run: docker build . --file Dockerfile --tag my-image-name:$(date +%s) +- name: Build the Docker image + run: docker build . --file Dockerfile --tag my-image-name:${{ github.sha }} From a585df630d075684256e8901eff9af4ef93006d3 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Sat, 10 May 2025 04:02:45 +0700 Subject: [PATCH 035/232] Update docker-image.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .github/workflows/docker-image.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index b37794b4a7f85..e0c9c518e8748 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -17,5 +17,5 @@ jobs: steps: - uses: actions/checkout@v4 -- name: Build the Docker image - run: docker build . --file Dockerfile --tag my-image-name:${{ github.sha }} + - name: Build the Docker image + run: docker build . --file Dockerfile --tag my-image-name:${{ github.sha }} From 3fb94af1686be281d6ea3e86fb6977bdd7e27bfd Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Sun, 27 Apr 2025 06:45:56 +0700 Subject: [PATCH 036/232] Revert "chore: fix isolate tests (#10344)" This reverts commit 70ded2b35f95ee9b4ee94f5e44961914d30a87f7. --- crates/forge/tests/cli/test_optimizer.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/forge/tests/cli/test_optimizer.rs b/crates/forge/tests/cli/test_optimizer.rs index 6c286c52793ec..944abed57ff30 100644 --- a/crates/forge/tests/cli/test_optimizer.rs +++ b/crates/forge/tests/cli/test_optimizer.rs @@ -1347,7 +1347,6 @@ Compiling 21 files with [..] }); // Test preprocessed contracts with decode internal fns. -#[cfg(not(feature = "isolate-by-default"))] forgetest_init!(preprocess_contract_with_decode_internal, |prj, cmd| { prj.update_config(|config| { config.dynamic_test_linking = true; From 6949f7f91c979f391192d9aa6877d31257b3d518 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Sun, 25 May 2025 06:07:02 +0700 Subject: [PATCH 037/232] Delete .github/workflows/jekyll.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .github/workflows/jekyll.yml | 65 ------------------------------------ 1 file changed, 65 deletions(-) delete mode 100644 .github/workflows/jekyll.yml diff --git a/.github/workflows/jekyll.yml b/.github/workflows/jekyll.yml deleted file mode 100644 index 501686bcc9563..0000000000000 --- a/.github/workflows/jekyll.yml +++ /dev/null @@ -1,65 +0,0 @@ -# This workflow uses actions that are not certified by GitHub. -# They are provided by a third-party and are governed by -# separate terms of service, privacy policy, and support -# documentation. - -# Sample workflow for building and deploying a Jekyll site to GitHub Pages -name: Deploy Jekyll site to Pages - -on: - # Runs on pushes targeting the default branch - push: - branches: ["master"] - - # Allows you to run this workflow manually from the Actions tab - workflow_dispatch: - -# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages -permissions: - contents: read - pages: write - id-token: write - -# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. -# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. -concurrency: - group: "pages" - cancel-in-progress: false - -jobs: - # Build job - build: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Setup Ruby - # https://github.com/ruby/setup-ruby/releases/tag/v1.207.0 - uses: ruby/setup-ruby@4a9ddd6f338a97768b8006bf671dfbad383215f4 - with: - ruby-version: '3.1' # Not needed with a .ruby-version file - bundler-cache: true # runs 'bundle install' and caches installed gems automatically - cache-version: 0 # Increment this number if you need to re-download cached gems - - name: Setup Pages - id: pages - uses: actions/configure-pages@v5 - - name: Build with Jekyll - # Outputs to the './_site' directory by default - run: bundle exec jekyll build --baseurl "${{ steps.pages.outputs.base_path }}" - env: - JEKYLL_ENV: production - - name: Upload artifact - # Automatically uploads an artifact from the './_site' directory by default - uses: actions/upload-pages-artifact@v3 - - # Deployment job - deploy: - environment: - name: github-pages - url: ${{ steps.deployment.outputs.page_url }} - runs-on: ubuntu-latest - needs: build - steps: - - name: Deploy to GitHub Pages - id: deployment - uses: actions/deploy-pages@v4 From 7aa139ecd096ab7ebd551e5196b497a3f354c682 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Sun, 25 May 2025 23:26:49 +0700 Subject: [PATCH 038/232] Update test.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .github/workflows/test.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0486f2237f10b..d3fe0f910e5b4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -38,9 +38,10 @@ jobs: uses: peaceiris/actions-gh-pages@v3 if: github.event_name == 'push' && github.ref == 'refs/heads/master' with: - github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: target/doc - force_orphan: true + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: target/doc + force_orphan: true + commit_message: "Deploy documentation [skip ci]" doctest: runs-on: ubuntu-latest From f0897aa843fdcc48871abde95b9597cdffe263d1 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Sun, 25 May 2025 23:26:49 +0700 Subject: [PATCH 039/232] Update test.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .github/workflows/test.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0486f2237f10b..d3fe0f910e5b4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -38,9 +38,10 @@ jobs: uses: peaceiris/actions-gh-pages@v3 if: github.event_name == 'push' && github.ref == 'refs/heads/master' with: - github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: target/doc - force_orphan: true + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: target/doc + force_orphan: true + commit_message: "Deploy documentation [skip ci]" doctest: runs-on: ubuntu-latest From 7bdfb1b6ad2c5221781bed53f4a470828c5570cc Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Sun, 25 May 2025 23:08:28 +0700 Subject: [PATCH 040/232] Potential fix for code scanning alert no. 19: Workflow does not contain permissions Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .github/workflows/release.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4bf0543fb7482..1b18d4ad1dd2c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -295,6 +295,9 @@ jobs: runs-on: ubuntu-latest needs: [prepare, release-docker, release, cleanup] if: failure() + permissions: + issues: write + contents: read steps: - uses: actions/checkout@v4 - uses: JasonEtco/create-an-issue@v2 From 3be9159c06ac637f76a65ef1e9e7299b7257aa8f Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Mon, 26 May 2025 01:43:49 +0700 Subject: [PATCH 041/232] Update test.yml (#46) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .github/workflows/test.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d3fe0f910e5b4..f4d5d2d361f5a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -42,7 +42,15 @@ jobs: publish_dir: target/doc force_orphan: true commit_message: "Deploy documentation [skip ci]" - + - name: Push changes + git config user.name "GitHub Actions" + git config user.email "actions@github.com" + to pass before a push is allowed. + git commit -S -m "Auto-update gh-pages" + git push origin --force gh-pages + +### Solution **Review Repository Rules:** + doctest: runs-on: ubuntu-latest timeout-minutes: 30 From 428d049479cdd617336544f38a0646b60c5f8c68 Mon Sep 17 00:00:00 2001 From: zerosnacks <95942363+zerosnacks@users.noreply.github.com> Date: Mon, 26 May 2025 12:46:14 +0200 Subject: [PATCH 042/232] chore(deps): bump revm to 24.0.0 (#10601) --- Cargo.lock | 208 +++++++++---------- Cargo.toml | 68 +++--- crates/anvil/core/src/eth/transaction/mod.rs | 4 +- crates/anvil/src/eth/backend/mem/mod.rs | 4 +- crates/anvil/tests/it/optimism.rs | 2 +- crates/cheatcodes/src/inspector.rs | 9 +- crates/debugger/src/tui/draw.rs | 1 - 7 files changed, 139 insertions(+), 157 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e972d3906b5dc..a8c4a15e7bc6d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -58,9 +58,9 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "alloy-chains" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5848366a4f08dca1caca0a6151294a4799fe2e59ba25df100491d92e0b921b1c" +checksum = "517e5acbd38b6d4c59da380e8bbadc6d365bf001903ce46cf5521c53c647e07b" dependencies = [ "alloy-primitives", "num_enum", @@ -74,10 +74,10 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7329eb72d95576dfb8813175bcf671198fb24266b0b3e520052a513e30c284df" dependencies = [ - "alloy-eips 1.0.7", + "alloy-eips", "alloy-primitives", "alloy-rlp", - "alloy-serde 1.0.7", + "alloy-serde", "alloy-trie", "auto_impl", "c-kzg", @@ -99,10 +99,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f31b286aeef04a32720c10defd21c3aa6c626154ac442b55f6d472caeb1c6741" dependencies = [ "alloy-consensus", - "alloy-eips 1.0.7", + "alloy-eips", "alloy-primitives", "alloy-rlp", - "alloy-serde 1.0.7", + "alloy-serde", "serde", ] @@ -185,26 +185,6 @@ dependencies = [ "thiserror 2.0.12", ] -[[package]] -name = "alloy-eips" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "609515c1955b33af3d78d26357540f68c5551a90ef58fd53def04f2aa074ec43" -dependencies = [ - "alloy-eip2124", - "alloy-eip2930", - "alloy-eip7702", - "alloy-primitives", - "alloy-rlp", - "alloy-serde 0.14.0", - "auto_impl", - "c-kzg", - "derive_more 2.0.1", - "either", - "serde", - "sha2 0.10.9", -] - [[package]] name = "alloy-eips" version = "1.0.7" @@ -216,7 +196,7 @@ dependencies = [ "alloy-eip7702", "alloy-primitives", "alloy-rlp", - "alloy-serde 1.0.7", + "alloy-serde", "auto_impl", "c-kzg", "derive_more 2.0.1", @@ -241,12 +221,12 @@ dependencies = [ [[package]] name = "alloy-evm" -version = "0.9.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8c5b34c78c42525917b236e4135b1951ca183ede4004b594db0effee8bed169" +checksum = "394b09cf3a32773eedf11828987f9c72dfa74545040be0422e3f5f09a2a3fab9" dependencies = [ "alloy-consensus", - "alloy-eips 1.0.7", + "alloy-eips", "alloy-hardforks", "alloy-primitives", "alloy-sol-types", @@ -264,9 +244,9 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b81b2dfd278d58af8bfde8753fa4685407ba8fbad8bc88a2bb0e065eed48478" dependencies = [ - "alloy-eips 1.0.7", + "alloy-eips", "alloy-primitives", - "alloy-serde 1.0.7", + "alloy-serde", "alloy-trie", "serde", ] @@ -318,13 +298,13 @@ checksum = "f0ed07e76fbc72790a911ea100cdfbe85b1f12a097c91b948042e854959d140e" dependencies = [ "alloy-consensus", "alloy-consensus-any", - "alloy-eips 1.0.7", + "alloy-eips", "alloy-json-rpc", "alloy-network-primitives", "alloy-primitives", "alloy-rpc-types-any", "alloy-rpc-types-eth", - "alloy-serde 1.0.7", + "alloy-serde", "alloy-signer", "alloy-sol-types", "async-trait", @@ -343,20 +323,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f05aa52713c376f797b3c7077708585f22a5c3053a7b1b2b355ea98edeb2052d" dependencies = [ "alloy-consensus", - "alloy-eips 1.0.7", + "alloy-eips", "alloy-primitives", - "alloy-serde 1.0.7", + "alloy-serde", "serde", ] [[package]] name = "alloy-op-evm" -version = "0.9.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4fda8b1920a38a5adc607d6ff7be1e8991e16ffcf97bb12765644b87331c598" +checksum = "9f32538cc243ec5d4603da9845cc2f5254c6a3a78e82475beb1a2a1de6c0d36c" dependencies = [ "alloy-consensus", - "alloy-eips 1.0.7", + "alloy-eips", "alloy-evm", "alloy-op-hardforks", "alloy-primitives", @@ -415,7 +395,7 @@ checksum = "05a3f7a59c276c6e410267e77a166f9297dbe74e4605f1abf625e29d85c53144" dependencies = [ "alloy-chains", "alloy-consensus", - "alloy-eips 1.0.7", + "alloy-eips", "alloy-json-rpc", "alloy-network", "alloy-network-primitives", @@ -535,7 +515,7 @@ dependencies = [ "alloy-rpc-types-eth", "alloy-rpc-types-trace", "alloy-rpc-types-txpool", - "alloy-serde 1.0.7", + "alloy-serde", "serde", ] @@ -547,7 +527,7 @@ checksum = "51e15bd6456742d6dcadacf3cd238a90a8a7aa9f00bc7cc641ae272f5d3f5d4f" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", - "alloy-serde 1.0.7", + "alloy-serde", "serde", ] @@ -559,7 +539,7 @@ checksum = "67971a228100ac65bd86e90439028853435f21796330ef08f00a70a918a84126" dependencies = [ "alloy-consensus-any", "alloy-rpc-types-eth", - "alloy-serde 1.0.7", + "alloy-serde", ] [[package]] @@ -579,10 +559,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2bcf49fe91b3d621440dcc5bb067afaeba5ca4b07f59e42fb7af42944146a8c0" dependencies = [ "alloy-consensus", - "alloy-eips 1.0.7", + "alloy-eips", "alloy-primitives", "alloy-rlp", - "alloy-serde 1.0.7", + "alloy-serde", "derive_more 2.0.1", "jsonwebtoken", "rand 0.8.5", @@ -598,11 +578,11 @@ checksum = "89d9b4293dfd4721781d33ee40de060376932d4a55d421cf6618ad66ff97cc52" dependencies = [ "alloy-consensus", "alloy-consensus-any", - "alloy-eips 1.0.7", + "alloy-eips", "alloy-network-primitives", "alloy-primitives", "alloy-rlp", - "alloy-serde 1.0.7", + "alloy-serde", "alloy-sol-types", "itertools 0.14.0", "serde", @@ -618,7 +598,7 @@ checksum = "7f68f020452c0d570b4eee22d4ffda9e4eda68ebcf67e1199d6dff48097f442b" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", - "alloy-serde 1.0.7", + "alloy-serde", "serde", "serde_json", "thiserror 2.0.12", @@ -632,21 +612,10 @@ checksum = "62a82f15f296c2c83c55519d21ca07801fb58b118878b0f4777250968e49f4fe" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", - "alloy-serde 1.0.7", + "alloy-serde", "serde", ] -[[package]] -name = "alloy-serde" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4dba6ff08916bc0a9cbba121ce21f67c0b554c39cf174bc7b9df6c651bd3c3b" -dependencies = [ - "alloy-primitives", - "serde", - "serde_json", -] - [[package]] name = "alloy-serde" version = "1.0.7" @@ -1051,7 +1020,7 @@ dependencies = [ "alloy-consensus", "alloy-contract", "alloy-dyn-abi", - "alloy-eips 1.0.7", + "alloy-eips", "alloy-evm", "alloy-genesis", "alloy-network", @@ -1061,7 +1030,7 @@ dependencies = [ "alloy-pubsub", "alloy-rlp", "alloy-rpc-types", - "alloy-serde 1.0.7", + "alloy-serde", "alloy-signer", "alloy-signer-local", "alloy-sol-types", @@ -1113,12 +1082,12 @@ version = "1.2.1" dependencies = [ "alloy-consensus", "alloy-dyn-abi", - "alloy-eips 1.0.7", + "alloy-eips", "alloy-network", "alloy-primitives", "alloy-rlp", "alloy-rpc-types", - "alloy-serde 1.0.7", + "alloy-serde", "bytes", "foundry-common", "foundry-evm", @@ -2389,7 +2358,7 @@ dependencies = [ "alloy-provider", "alloy-rlp", "alloy-rpc-types", - "alloy-serde 1.0.7", + "alloy-serde", "alloy-signer", "alloy-signer-local", "alloy-sol-types", @@ -3814,7 +3783,7 @@ dependencies = [ "alloy-primitives", "alloy-provider", "alloy-rpc-types", - "alloy-serde 1.0.7", + "alloy-serde", "alloy-signer", "alloy-signer-local", "alloy-transport", @@ -3947,13 +3916,13 @@ dependencies = [ "alloy-chains", "alloy-consensus", "alloy-dyn-abi", - "alloy-eips 1.0.7", + "alloy-eips", "alloy-json-abi", "alloy-network", "alloy-primitives", "alloy-provider", "alloy-rpc-types", - "alloy-serde 1.0.7", + "alloy-serde", "alloy-signer", "clap", "dialoguer", @@ -4145,7 +4114,7 @@ version = "1.2.1" dependencies = [ "alloy-chains", "alloy-dyn-abi", - "alloy-eips 1.0.7", + "alloy-eips", "alloy-ens", "alloy-json-abi", "alloy-primitives", @@ -4191,7 +4160,7 @@ version = "1.2.1" dependencies = [ "alloy-consensus", "alloy-dyn-abi", - "alloy-eips 1.0.7", + "alloy-eips", "alloy-json-abi", "alloy-json-rpc", "alloy-network", @@ -4200,7 +4169,7 @@ dependencies = [ "alloy-pubsub", "alloy-rpc-client", "alloy-rpc-types", - "alloy-serde 1.0.7", + "alloy-serde", "alloy-sol-types", "alloy-transport", "alloy-transport-http", @@ -4249,7 +4218,7 @@ dependencies = [ "alloy-network", "alloy-primitives", "alloy-rpc-types", - "alloy-serde 1.0.7", + "alloy-serde", "chrono", "foundry-macros", "revm", @@ -4570,9 +4539,9 @@ dependencies = [ [[package]] name = "foundry-fork-db" -version = "0.14.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c99831be91edd8a025fa60443b5404ad407708bc337d2e20440d498b5806fab8" +checksum = "b02fb598e4a8ae7b7af7c256081a419b071eacf5e03537806b339b3151409403" dependencies = [ "alloy-consensus", "alloy-primitives", @@ -6169,9 +6138,9 @@ checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" [[package]] name = "newtype-uuid" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee3224f0e8be7c2a1ebc77ef9c3eecb90f55c6594399ee825de964526b3c9056" +checksum = "a8ba303c7a8f8fdee1fe1513cfd918f50f1c69bf65c91b39217bfc2b2af5c081" dependencies = [ "uuid 1.17.0", ] @@ -6487,17 +6456,17 @@ dependencies = [ [[package]] name = "op-alloy-consensus" -version = "0.16.0" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f318b09e24148f07392c5e011bae047a0043851f9041145df5f3b01e4fedd1e" +checksum = "bb35d16e5420e43e400a235783e3d18b6ba564917139b668b48e9ac42cb3d35a" dependencies = [ "alloy-consensus", - "alloy-eips 1.0.7", + "alloy-eips", "alloy-network", "alloy-primitives", "alloy-rlp", "alloy-rpc-types-eth", - "alloy-serde 1.0.7", + "alloy-serde", "derive_more 2.0.1", "serde", "thiserror 2.0.12", @@ -6511,16 +6480,16 @@ checksum = "4ef71f23a8caf6f2a2d5cafbdc44956d44e6014dcb9aa58abf7e4e6481c6ec34" [[package]] name = "op-alloy-rpc-types" -version = "0.16.0" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15ede8322c10c21249de4fced204e2af4978972e715afee34b6fe684d73880cf" +checksum = "7534a0ec6b8409edc511acbe77abe7805aa63129b98e9a915bb4eb8555eaa6ff" dependencies = [ "alloy-consensus", - "alloy-eips 1.0.7", + "alloy-eips", "alloy-network-primitives", "alloy-primitives", "alloy-rpc-types-eth", - "alloy-serde 1.0.7", + "alloy-serde", "derive_more 2.0.1", "op-alloy-consensus", "serde", @@ -6530,8 +6499,9 @@ dependencies = [ [[package]] name = "op-revm" -version = "4.0.2" -source = "git+https://github.com/bluealloy/revm.git?rev=b5808253#b580825320708f0c47d3734ceab03d90c0b11ba1" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47296d449fbe2d5cc74ab6e1213dee88cae3e2fd238343bec605c3c687bbcfab" dependencies = [ "auto_impl", "once_cell", @@ -7585,8 +7555,9 @@ dependencies = [ [[package]] name = "revm" -version = "23.1.0" -source = "git+https://github.com/bluealloy/revm.git?rev=b5808253#b580825320708f0c47d3734ceab03d90c0b11ba1" +version = "24.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d3ae9d1b08303eb5150dcf820a29e14235cf3f24f6c09024458a4dcbffe6695" dependencies = [ "revm-bytecode", "revm-context", @@ -7603,8 +7574,9 @@ dependencies = [ [[package]] name = "revm-bytecode" -version = "4.0.0" -source = "git+https://github.com/bluealloy/revm.git?rev=b5808253#b580825320708f0c47d3734ceab03d90c0b11ba1" +version = "4.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91f9b90b3bab18942252de2d970ee8559794c49ca7452b2cc1774456040f8fb" dependencies = [ "bitvec", "once_cell", @@ -7615,8 +7587,9 @@ dependencies = [ [[package]] name = "revm-context" -version = "4.1.0" -source = "git+https://github.com/bluealloy/revm.git?rev=b5808253#b580825320708f0c47d3734ceab03d90c0b11ba1" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b181214eb2bbb76ee9d6195acba19857d991d2cdb9a65b7cb6939c30250a3966" dependencies = [ "cfg-if", "derive-where", @@ -7630,8 +7603,9 @@ dependencies = [ [[package]] name = "revm-context-interface" -version = "4.1.0" -source = "git+https://github.com/bluealloy/revm.git?rev=b5808253#b580825320708f0c47d3734ceab03d90c0b11ba1" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b844f48a411e62c7dde0f757bf5cce49c85b86d6fc1d3b2722c07f2bec4c3ce" dependencies = [ "alloy-eip2930", "alloy-eip7702", @@ -7645,10 +7619,11 @@ dependencies = [ [[package]] name = "revm-database" -version = "4.0.0" -source = "git+https://github.com/bluealloy/revm.git?rev=b5808253#b580825320708f0c47d3734ceab03d90c0b11ba1" +version = "4.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad3fbe34f6bb00a9c3155723b3718b9cb9f17066ba38f9eb101b678cd3626775" dependencies = [ - "alloy-eips 0.14.0", + "alloy-eips", "revm-bytecode", "revm-database-interface", "revm-primitives", @@ -7658,8 +7633,9 @@ dependencies = [ [[package]] name = "revm-database-interface" -version = "4.0.0" -source = "git+https://github.com/bluealloy/revm.git?rev=b5808253#b580825320708f0c47d3734ceab03d90c0b11ba1" +version = "4.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b8acd36784a6d95d5b9e1b7be3ce014f1e759abb59df1fa08396b30f71adc2a" dependencies = [ "auto_impl", "revm-primitives", @@ -7669,8 +7645,9 @@ dependencies = [ [[package]] name = "revm-handler" -version = "4.1.0" -source = "git+https://github.com/bluealloy/revm.git?rev=b5808253#b580825320708f0c47d3734ceab03d90c0b11ba1" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08a9204e3ac1a8edb850cc441a6a1d0f2251c0089e5fffdaba11566429e6c64e" dependencies = [ "auto_impl", "revm-bytecode", @@ -7686,8 +7663,9 @@ dependencies = [ [[package]] name = "revm-inspector" -version = "4.1.0" -source = "git+https://github.com/bluealloy/revm.git?rev=b5808253#b580825320708f0c47d3734ceab03d90c0b11ba1" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae4881eeae6ff35417c8569bc7cc03b6c0969869ee2c9b3945a39b4f9fa58bc5" dependencies = [ "auto_impl", "revm-context", @@ -7702,9 +7680,9 @@ dependencies = [ [[package]] name = "revm-inspectors" -version = "0.22.3" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f847f5e88a09ac84b36529fbe2fee80b3d8bbf91e9a7ae3ea856c4125d0d232" +checksum = "4b50ef375dbacefecfdacf8f02afc31df98acc5d8859a6f2b24d121ff2a740a8" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", @@ -7720,8 +7698,9 @@ dependencies = [ [[package]] name = "revm-interpreter" -version = "19.1.0" -source = "git+https://github.com/bluealloy/revm.git?rev=b5808253#b580825320708f0c47d3734ceab03d90c0b11ba1" +version = "20.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5ee65e57375c6639b0f50555e92a4f1b2434349dd32f52e2176f5c711171697" dependencies = [ "revm-bytecode", "revm-context-interface", @@ -7731,8 +7710,9 @@ dependencies = [ [[package]] name = "revm-precompile" -version = "20.1.0" -source = "git+https://github.com/bluealloy/revm.git?rev=b5808253#b580825320708f0c47d3734ceab03d90c0b11ba1" +version = "21.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f9311e735123d8d53a02af2aa81877bba185be7c141be7f931bb3d2f3af449c" dependencies = [ "ark-bls12-381", "ark-bn254", @@ -7755,8 +7735,9 @@ dependencies = [ [[package]] name = "revm-primitives" -version = "19.0.0" -source = "git+https://github.com/bluealloy/revm.git?rev=b5808253#b580825320708f0c47d3734ceab03d90c0b11ba1" +version = "19.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18ea2ea0134568ee1e14281ce52f60e2710d42be316888d464c53e37ff184fd8" dependencies = [ "alloy-primitives", "num_enum", @@ -7765,8 +7746,9 @@ dependencies = [ [[package]] name = "revm-state" -version = "4.0.0" -source = "git+https://github.com/bluealloy/revm.git?rev=b5808253#b580825320708f0c47d3734ceab03d90c0b11ba1" +version = "4.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0040c61c30319254b34507383ba33d85f92949933adf6525a2cede05d165e1fa" dependencies = [ "bitflags 2.9.1", "revm-bytecode", diff --git a/Cargo.toml b/Cargo.toml index 76f51d5337151..8686f046c2c14 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -200,7 +200,7 @@ foundry-linking = { path = "crates/linking" } # solc & compilation utilities foundry-block-explorers = { version = "0.17.0", default-features = false } foundry-compilers = { version = "0.16.1", default-features = false } -foundry-fork-db = "0.14" +foundry-fork-db = "0.15" solang-parser = { version = "=0.3.8", package = "foundry-solang-parser" } solar-ast = { version = "=0.1.3", default-features = false } solar-parse = { version = "=0.1.3", default-features = false } @@ -208,28 +208,28 @@ solar-interface = { version = "=0.1.3", default-features = false } solar-sema = { version = "=0.1.3", default-features = false } ## alloy -alloy-consensus = { version = "1.0.5", default-features = false } -alloy-contract = { version = "1.0.5", default-features = false } -alloy-eips = { version = "1.0.5", default-features = false } -alloy-ens = { version = "1.0.5", default-features = false } -alloy-genesis = { version = "1.0.5", default-features = false } -alloy-json-rpc = { version = "1.0.5", default-features = false } -alloy-network = { version = "1.0.5", default-features = false } -alloy-provider = { version = "1.0.5", default-features = false } -alloy-pubsub = { version = "1.0.5", default-features = false } -alloy-rpc-client = { version = "1.0.5", default-features = false } -alloy-rpc-types = { version = "1.0.5", default-features = true } -alloy-serde = { version = "1.0.5", default-features = false } -alloy-signer = { version = "1.0.5", default-features = false } -alloy-signer-aws = { version = "1.0.5", default-features = false } -alloy-signer-gcp = { version = "1.0.5", default-features = false } -alloy-signer-ledger = { version = "1.0.5", default-features = false } -alloy-signer-local = { version = "1.0.5", default-features = false } -alloy-signer-trezor = { version = "1.0.5", default-features = false } -alloy-transport = { version = "1.0.5", default-features = false } -alloy-transport-http = { version = "1.0.5", default-features = false } -alloy-transport-ipc = { version = "1.0.5", default-features = false } -alloy-transport-ws = { version = "1.0.5", default-features = false } +alloy-consensus = { version = "1.0.7", default-features = false } +alloy-contract = { version = "1.0.7", default-features = false } +alloy-eips = { version = "1.0.7", default-features = false } +alloy-ens = { version = "1.0.7", default-features = false } +alloy-genesis = { version = "1.0.7", default-features = false } +alloy-json-rpc = { version = "1.0.7", default-features = false } +alloy-network = { version = "1.0.7", default-features = false } +alloy-provider = { version = "1.0.7", default-features = false } +alloy-pubsub = { version = "1.0.7", default-features = false } +alloy-rpc-client = { version = "1.0.7", default-features = false } +alloy-rpc-types = { version = "1.0.7", default-features = true } +alloy-serde = { version = "1.0.7", default-features = false } +alloy-signer = { version = "1.0.7", default-features = false } +alloy-signer-aws = { version = "1.0.7", default-features = false } +alloy-signer-gcp = { version = "1.0.7", default-features = false } +alloy-signer-ledger = { version = "1.0.7", default-features = false } +alloy-signer-local = { version = "1.0.7", default-features = false } +alloy-signer-trezor = { version = "1.0.7", default-features = false } +alloy-transport = { version = "1.0.7", default-features = false } +alloy-transport-http = { version = "1.0.7", default-features = false } +alloy-transport-ipc = { version = "1.0.7", default-features = false } +alloy-transport-ws = { version = "1.0.7", default-features = false } ## alloy-core alloy-dyn-abi = "1.0" @@ -249,18 +249,18 @@ alloy-rlp = "0.3" alloy-trie = "0.8.1" ## op-alloy -op-alloy-consensus = "0.16.0" -op-alloy-rpc-types = "0.16.0" +op-alloy-consensus = "0.17.1" +op-alloy-rpc-types = "0.17.1" op-alloy-flz = "0.13.0" ## revm -revm = { version = "23.1.0", default-features = false } -revm-inspectors = { version = "0.22.3", features = ["serde"] } -op-revm = { version = "4.0.2", default-features = false } +revm = { version = "24.0.0", default-features = false } +revm-inspectors = { version = "0.23.0", features = ["serde"] } +op-revm = { version = "5.0.0", default-features = false } ## alloy-evm -alloy-evm = "0.9.1" -alloy-op-evm = "0.9.1" +alloy-evm = "0.10.0" +alloy-op-evm = "0.10.0" ## cli anstream = "0.6" @@ -390,12 +390,12 @@ zip-extract = "=0.2.1" # alloy-transport-ws = { git = "https://github.com/alloy-rs/alloy", rev = "7fab7ee" } ## alloy-evm -# alloy-evm = { git = "https://github.com/alloy-rs/evm.git", rev = "95f6a8a" } -# alloy-op-evm = { git = "https://github.com/alloy-rs/evm.git", rev = "95f6a8a" } +# alloy-evm = { git = "https://github.com/alloy-rs/evm.git", rev = "8076e12" } +# alloy-op-evm = { git = "https://github.com/alloy-rs/evm.git", rev = "8076e12" } ## revm -revm = { git = "https://github.com/bluealloy/revm.git", rev = "b5808253" } -op-revm = { git = "https://github.com/bluealloy/revm.git", rev = "b5808253" } +# revm = { git = "https://github.com/bluealloy/revm.git", rev = "b5808253" } +# op-revm = { git = "https://github.com/bluealloy/revm.git", rev = "b5808253" } # revm-inspectors = { git = "https://github.com/paradigmxyz/revm-inspectors.git", rev = "a625c04" } ## foundry diff --git a/crates/anvil/core/src/eth/transaction/mod.rs b/crates/anvil/core/src/eth/transaction/mod.rs index f6122b2893207..ae6a7262565ca 100644 --- a/crates/anvil/core/src/eth/transaction/mod.rs +++ b/crates/anvil/core/src/eth/transaction/mod.rs @@ -60,7 +60,7 @@ pub fn transaction_request_to_typed( from: from.unwrap_or_default(), source_hash: other.get_deserialized::("sourceHash")?.ok()?, to: to.unwrap_or_default(), - mint: Some(mint), + mint, value: value.unwrap_or_default(), gas_limit: gas.unwrap_or_default(), is_system_transaction: other.get_deserialized::("isSystemTx")?.ok()?, @@ -574,7 +574,7 @@ impl PendingTransaction { let deposit = DepositTransactionParts { source_hash: *source_hash, - mint: *mint, + mint: Some(*mint), is_system_transaction: *is_system_transaction, }; diff --git a/crates/anvil/src/eth/backend/mem/mod.rs b/crates/anvil/src/eth/backend/mem/mod.rs index a7b02ff39c059..321ed41ea3925 100644 --- a/crates/anvil/src/eth/backend/mem/mod.rs +++ b/crates/anvil/src/eth/backend/mem/mod.rs @@ -3178,8 +3178,8 @@ impl TransactionValidator for Backend { // 1. no gas cost check required since already have prepaid gas from L1 // 2. increment account balance by deposited amount before checking for sufficient // funds `tx.value <= existing account value + deposited value` - if value > account.balance + U256::from(deposit_tx.mint.unwrap_or_default()) { - warn!(target: "backend", "[{:?}] insufficient balance={}, required={} account={:?}", tx.hash(), account.balance + U256::from(deposit_tx.mint.unwrap_or_default()), value, *pending.sender()); + if value > account.balance + U256::from(deposit_tx.mint) { + warn!(target: "backend", "[{:?}] insufficient balance={}, required={} account={:?}", tx.hash(), account.balance + U256::from(deposit_tx.mint), value, *pending.sender()); return Err(InvalidTransactionError::InsufficientFunds); } } diff --git a/crates/anvil/tests/it/optimism.rs b/crates/anvil/tests/it/optimism.rs index e8bfe4d6560a5..f871cca724a97 100644 --- a/crates/anvil/tests/it/optimism.rs +++ b/crates/anvil/tests/it/optimism.rs @@ -200,7 +200,7 @@ async fn test_deposit_tx_checks_sufficient_funds_after_applying_deposited_value( source_hash: b256!("0x0000000000000000000000000000000000000000000000000000000000000000"), from: sender, to: TxKind::Call(recipient), - mint: Some(send_value), + mint: send_value, value: U256::from(send_value), gas_limit: 21_000, is_system_transaction: false, diff --git a/crates/cheatcodes/src/inspector.rs b/crates/cheatcodes/src/inspector.rs index 9677806893d3f..4d9b5cd5ef5ed 100644 --- a/crates/cheatcodes/src/inspector.rs +++ b/crates/cheatcodes/src/inspector.rs @@ -54,7 +54,7 @@ use revm::{ context_interface::{transaction::SignedAuthorization, CreateScheme}, handler::FrameResult, interpreter::{ - interpreter_types::{Jumps, LoopControl, MemoryTr}, + interpreter_types::{Jumps, MemoryTr}, CallInputs, CallOutcome, CallScheme, CreateInputs, CreateOutcome, FrameInput, Gas, Host, InstructionResult, Interpreter, InterpreterAction, InterpreterResult, }, @@ -1845,9 +1845,10 @@ impl Cheatcodes { if let Some(paused_gas) = self.gas_metering.paused_frames.last() { // Keep gas constant if paused. // Make sure we record the memory changes so that memory expansion is not paused. - let memory = interpreter.control.gas.memory; + let memory = *interpreter.control.gas.memory(); interpreter.control.gas = *paused_gas; - interpreter.control.gas.memory = memory; + interpreter.control.gas.memory_mut().words_num = memory.words_num; + interpreter.control.gas.memory_mut().expansion_cost = memory.expansion_cost; } else { // Record frame paused gas. self.gas_metering.paused_frames.push(interpreter.control.gas); @@ -1889,7 +1890,7 @@ impl Cheatcodes { #[cold] fn meter_gas_reset(&mut self, interpreter: &mut Interpreter) { - interpreter.control.gas = Gas::new(interpreter.control.gas().limit()); + interpreter.control.gas = Gas::new(interpreter.control.gas.limit()); self.gas_metering.reset = false; } diff --git a/crates/debugger/src/tui/draw.rs b/crates/debugger/src/tui/draw.rs index a918bc89ea733..580d6f958ac44 100644 --- a/crates/debugger/src/tui/draw.rs +++ b/crates/debugger/src/tui/draw.rs @@ -199,7 +199,6 @@ impl TUIContext<'_> { CallKind::CallCode => "Contract callcode", CallKind::DelegateCall => "Contract delegatecall", CallKind::AuthCall => "Contract authcall", - CallKind::EOFCreate => "EOF contract creation", }; let title = format!( "{} {} ", From 7ff1d3b2d4ae18d07495a85b1626be7cdf291a5e Mon Sep 17 00:00:00 2001 From: pistomat Date: Mon, 26 May 2025 16:26:49 +0200 Subject: [PATCH 043/232] feat: implement add_balance endpoint (#10636) --- crates/anvil/core/src/eth/mod.rs | 14 +++++++++++++- crates/anvil/src/eth/api.rs | 13 +++++++++++++ crates/anvil/tests/it/fork.rs | 16 ++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/crates/anvil/core/src/eth/mod.rs b/crates/anvil/core/src/eth/mod.rs index df07f62ee730c..ac7db74892003 100644 --- a/crates/anvil/core/src/eth/mod.rs +++ b/crates/anvil/core/src/eth/mod.rs @@ -361,9 +361,21 @@ pub enum EthRequest { SetRpcUrl(String), /// Modifies the balance of an account. - #[serde(rename = "anvil_setBalance", alias = "hardhat_setBalance")] + #[serde( + rename = "anvil_setBalance", + alias = "hardhat_setBalance", + alias = "tenderly_setBalance" + )] SetBalance(Address, #[serde(deserialize_with = "deserialize_number")] U256), + /// Increases the balance of an account. + #[serde( + rename = "anvil_addBalance", + alias = "hardhat_addBalance", + alias = "tenderly_addBalance" + )] + AddBalance(Address, #[serde(deserialize_with = "deserialize_number")] U256), + /// Modifies the ERC20 balance of an account. #[serde( rename = "anvil_dealERC20", diff --git a/crates/anvil/src/eth/api.rs b/crates/anvil/src/eth/api.rs index 243ae88440e8d..ec6fbeb4227a1 100644 --- a/crates/anvil/src/eth/api.rs +++ b/crates/anvil/src/eth/api.rs @@ -356,6 +356,9 @@ impl EthApi { EthRequest::SetBalance(addr, val) => { self.anvil_set_balance(addr, val).await.to_rpc_result() } + EthRequest::AddBalance(addr, val) => { + self.anvil_add_balance(addr, val).await.to_rpc_result() + } EthRequest::DealERC20(addr, token_addr, val) => { self.anvil_deal_erc20(addr, token_addr, val).await.to_rpc_result() } @@ -1856,6 +1859,16 @@ impl EthApi { Ok(()) } + /// Increases the balance of an account. + /// + /// Handler for RPC call: `anvil_addBalance` + pub async fn anvil_add_balance(&self, address: Address, balance: U256) -> Result<()> { + node_info!("anvil_addBalance"); + let current_balance = self.backend.get_balance(address, None).await?; + self.backend.set_balance(address, current_balance + balance).await?; + Ok(()) + } + /// Deals ERC20 tokens to a address /// /// Handler for RPC call: `anvil_dealERC20` diff --git a/crates/anvil/tests/it/fork.rs b/crates/anvil/tests/it/fork.rs index 54bae673a6bd0..e4e1cda1a31d3 100644 --- a/crates/anvil/tests/it/fork.rs +++ b/crates/anvil/tests/it/fork.rs @@ -1490,6 +1490,22 @@ async fn test_set_erc20_balance() { assert_eq!(new_balance, value); } +#[tokio::test(flavor = "multi_thread")] +async fn test_add_balance() { + let config: NodeConfig = fork_config(); + let address = config.genesis_accounts[0].address(); + let (api, _handle) = spawn(config).await; + + let start_balance = U256::from(100_000_u64); + api.anvil_set_balance(address, start_balance).await.unwrap(); + + let balance_increase = U256::from(50_000_u64); + api.anvil_add_balance(address, balance_increase).await.unwrap(); + + let new_balance = api.balance(address, None).await.unwrap(); + assert_eq!(new_balance, start_balance + balance_increase); +} + #[tokio::test(flavor = "multi_thread")] async fn test_reset_updates_cache_path_when_rpc_url_not_provided() { let config: NodeConfig = fork_config(); From 15d07f0431bf217aa292e3ffe3dbffd4a48dae48 Mon Sep 17 00:00:00 2001 From: zark <77061323+zarkk01@users.noreply.github.com> Date: Mon, 26 May 2025 23:21:59 +0300 Subject: [PATCH 044/232] fix(bindings): ensure forge bind generates snake_case file names (#10622) * fix(bindings): ensure forge bind generates snake_case file names * refactor: use heck crate for snake_case conversion --------- Co-authored-by: zerosnacks <95942363+zerosnacks@users.noreply.github.com> --- Cargo.lock | 1 + crates/sol-macro-gen/Cargo.toml | 2 ++ crates/sol-macro-gen/src/sol_macro_gen.rs | 8 +++++--- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a8c4a15e7bc6d..c05a8b99f5d05 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3978,6 +3978,7 @@ dependencies = [ "alloy-sol-macro-input", "eyre", "foundry-common", + "heck", "prettyplease", "proc-macro2", "quote", diff --git a/crates/sol-macro-gen/Cargo.toml b/crates/sol-macro-gen/Cargo.toml index 79b47880f33f9..b983dd6a762b8 100644 --- a/crates/sol-macro-gen/Cargo.toml +++ b/crates/sol-macro-gen/Cargo.toml @@ -26,3 +26,5 @@ prettyplease.workspace = true serde_json.workspace = true eyre.workspace = true + +heck.workspace = true diff --git a/crates/sol-macro-gen/src/sol_macro_gen.rs b/crates/sol-macro-gen/src/sol_macro_gen.rs index 657dd4cbb8458..1e40d51169695 100644 --- a/crates/sol-macro-gen/src/sol_macro_gen.rs +++ b/crates/sol-macro-gen/src/sol_macro_gen.rs @@ -21,6 +21,8 @@ use std::{ str::FromStr, }; +use heck::ToSnakeCase; + pub struct SolMacroGen { pub path: PathBuf, pub name: String, @@ -209,7 +211,7 @@ edition = "2021" for instance in &self.instances { let contents = instance.expansion.as_ref().unwrap(); - let name = instance.name.to_lowercase(); + let name = instance.name.to_snake_case(); let path = src.join(format!("{name}.rs")); let file = syn::parse2(contents.clone()) .wrap_err_with(|| parse_error(&format!("{}:{}", path.display(), name)))?; @@ -266,7 +268,7 @@ edition = "2021" .to_string(); for instance in &self.instances { - let name = instance.name.to_lowercase(); + let name = instance.name.to_snake_case(); if !single_file { // Module write_mod_name(&mut mod_contents, &name)?; @@ -328,7 +330,7 @@ edition = "2021" )?; if !single_file { for instance in &self.instances { - let name = instance.name.to_lowercase(); + let name = instance.name.to_snake_case(); let path = if is_mod { crate_path.join(format!("{name}.rs")) } else { From 1e705a697ff01d4267a54b2052de1f7204baf7fb Mon Sep 17 00:00:00 2001 From: 0xrusowsky <90208954+0xrusowsky@users.noreply.github.com> Date: Mon, 26 May 2025 16:04:58 -0500 Subject: [PATCH 045/232] chore: standardize lint help + validate docs existance (#10639) --- crates/forge/tests/cli/lint.rs | 53 +++++++++++++++++++ crates/lint/src/linter.rs | 13 ++--- crates/lint/src/sol/gas/keccak.rs | 3 +- crates/lint/src/sol/high/incorrect_shift.rs | 3 +- crates/lint/src/sol/info/mixed_case.rs | 3 +- crates/lint/src/sol/info/pascal_case.rs | 3 +- .../lint/src/sol/info/screaming_snake_case.rs | 3 +- crates/lint/src/sol/macros.rs | 10 ++-- crates/lint/src/sol/med/div_mul.rs | 3 +- crates/lint/src/sol/mod.rs | 4 +- .../lint/testdata/DivideBeforeMultiply.stderr | 6 +++ crates/lint/testdata/IncorrectShift.stderr | 5 ++ crates/lint/testdata/Keccak256.stderr | 2 + crates/lint/testdata/MixedCase.stderr | 18 ++++--- .../lint/testdata/ScreamingSnakeCase.stderr | 12 +++-- crates/lint/testdata/StructPascalCase.stderr | 12 ++--- 16 files changed, 110 insertions(+), 43 deletions(-) diff --git a/crates/forge/tests/cli/lint.rs b/crates/forge/tests/cli/lint.rs index 94599eb059b17..2223d1cf11fce 100644 --- a/crates/forge/tests/cli/lint.rs +++ b/crates/forge/tests/cli/lint.rs @@ -1,3 +1,4 @@ +use forge_lint::{linter::Lint, sol::med::REGISTERED_LINTS}; use foundry_config::{LintSeverity, LinterConfig}; const CONTRACT: &str = r#" @@ -53,6 +54,7 @@ warning[divide-before-multiply]: multiplication should occur before division to 16 | (1 / 2) * 3; | ----------- | + = help: https://book.getfoundry.sh/reference/forge/forge-lint#divide-before-multiply "#]]); @@ -75,6 +77,7 @@ note[mixed-case-variable]: mutable variables should use mixedCase 6 | uint256 VARIABLE_MIXED_CASE_INFO; | ------------------------ | + = help: https://book.getfoundry.sh/reference/forge/forge-lint#mixed-case-variable "#]]); @@ -109,6 +112,7 @@ note[mixed-case-variable]: mutable variables should use mixedCase 6 | uint256 VARIABLE_MIXED_CASE_INFO; | ------------------------ | + = help: https://book.getfoundry.sh/reference/forge/forge-lint#mixed-case-variable "#]]); @@ -134,6 +138,7 @@ warning[divide-before-multiply]: multiplication should occur before division to 16 | (1 / 2) * 3; | ----------- | + = help: https://book.getfoundry.sh/reference/forge/forge-lint#divide-before-multiply "#]]); @@ -160,8 +165,56 @@ warning[incorrect-shift]: the order of args in a shift operation is incorrect 13 | result = 8 >> localValue; | --------------- | + = help: https://book.getfoundry.sh/reference/forge/forge-lint#incorrect-shift "# ]]); }); + +#[tokio::test] +async fn ensure_lint_rule_docs() { + const FOUNDRY_BOOK_LINT_PAGE_URL: &str = + "https://book.getfoundry.sh/reference/forge/forge-lint"; + + // Fetch the content of the lint reference + let content = match reqwest::get(FOUNDRY_BOOK_LINT_PAGE_URL).await { + Ok(resp) => { + if !resp.status().is_success() { + panic!( + "Failed to fetch Foundry Book lint page ({FOUNDRY_BOOK_LINT_PAGE_URL}). Status: {status}", + status = resp.status() + ); + } + match resp.text().await { + Ok(text) => text, + Err(e) => { + panic!("Failed to read response text: {e}"); + } + } + } + Err(e) => { + panic!("Failed to fetch Foundry Book lint page ({FOUNDRY_BOOK_LINT_PAGE_URL}): {e}",); + } + }; + + // Ensure no missing lints + let mut missing_lints = Vec::new(); + for lint in REGISTERED_LINTS { + let selector = format!("#{}", lint.id()); + if !content.contains(&selector) { + missing_lints.push(lint.id()); + } + } + + if !missing_lints.is_empty() { + let mut msg = String::from( + "Foundry Book lint validation failed. The following lints must be added to the docs:\n", + ); + for lint in missing_lints { + msg.push_str(&format!(" - {lint}\n")); + } + msg.push_str("Please open a PR: https://github.com/foundry-rs/book"); + panic!("{msg}"); + } +} diff --git a/crates/lint/src/linter.rs b/crates/lint/src/linter.rs index 6c188ff86497f..2c11e0222a286 100644 --- a/crates/lint/src/linter.rs +++ b/crates/lint/src/linter.rs @@ -31,9 +31,7 @@ pub trait Lint { fn id(&self) -> &'static str; fn severity(&self) -> Severity; fn description(&self) -> &'static str; - fn help(&self) -> Option<&'static str> { - None - } + fn help(&self) -> &'static str; } pub struct LintContext<'s> { @@ -48,19 +46,14 @@ impl<'s> LintContext<'s> { // Helper method to emit diagnostics easily from passes pub fn emit(&self, lint: &'static L, span: Span) { - let (desc, help) = match (self.desc, lint.help()) { - (true, Some(help)) => (lint.description(), help), - (true, None) => (lint.description(), ""), - (false, _) => ("", ""), - }; - + let desc = if self.desc { lint.description() } else { "" }; let diag: DiagBuilder<'_, ()> = self .sess .dcx .diag(lint.severity().into(), desc) .code(DiagId::new_str(lint.id())) .span(MultiSpan::from_span(span)) - .help(help); + .help(lint.help()); diag.emit(); } diff --git a/crates/lint/src/sol/gas/keccak.rs b/crates/lint/src/sol/gas/keccak.rs index f4031554b90ec..7316f4c4239b7 100644 --- a/crates/lint/src/sol/gas/keccak.rs +++ b/crates/lint/src/sol/gas/keccak.rs @@ -11,8 +11,7 @@ declare_forge_lint!( ASM_KECCAK256, Severity::Gas, "asm-keccak256", - "hash using inline assembly to save gas", - "" + "hash using inline assembly to save gas" ); impl<'ast> EarlyLintPass<'ast> for AsmKeccak256 { diff --git a/crates/lint/src/sol/high/incorrect_shift.rs b/crates/lint/src/sol/high/incorrect_shift.rs index 6d038d86382cd..8d2326c5cc9f9 100644 --- a/crates/lint/src/sol/high/incorrect_shift.rs +++ b/crates/lint/src/sol/high/incorrect_shift.rs @@ -10,8 +10,7 @@ declare_forge_lint!( INCORRECT_SHIFT, Severity::High, "incorrect-shift", - "the order of args in a shift operation is incorrect", - "" + "the order of args in a shift operation is incorrect" ); impl<'ast> EarlyLintPass<'ast> for IncorrectShift { diff --git a/crates/lint/src/sol/info/mixed_case.rs b/crates/lint/src/sol/info/mixed_case.rs index 035c21ef592c1..5e839e9f313cf 100644 --- a/crates/lint/src/sol/info/mixed_case.rs +++ b/crates/lint/src/sol/info/mixed_case.rs @@ -10,8 +10,7 @@ declare_forge_lint!( MIXED_CASE_FUNCTION, Severity::Info, "mixed-case-function", - "function names should use mixedCase", - "https://docs.soliditylang.org/en/latest/style-guide.html#function-names" + "function names should use mixedCase" ); impl<'ast> EarlyLintPass<'ast> for MixedCaseFunction { diff --git a/crates/lint/src/sol/info/pascal_case.rs b/crates/lint/src/sol/info/pascal_case.rs index 435debd66ac3c..60cafbc8365a3 100644 --- a/crates/lint/src/sol/info/pascal_case.rs +++ b/crates/lint/src/sol/info/pascal_case.rs @@ -10,8 +10,7 @@ declare_forge_lint!( PASCAL_CASE_STRUCT, Severity::Info, "pascal-case-struct", - "structs should use PascalCase", - "https://docs.soliditylang.org/en/latest/style-guide.html#struct-names" + "structs should use PascalCase" ); impl<'ast> EarlyLintPass<'ast> for PascalCaseStruct { diff --git a/crates/lint/src/sol/info/screaming_snake_case.rs b/crates/lint/src/sol/info/screaming_snake_case.rs index 528638181b126..ccc978029b8a4 100644 --- a/crates/lint/src/sol/info/screaming_snake_case.rs +++ b/crates/lint/src/sol/info/screaming_snake_case.rs @@ -10,8 +10,7 @@ declare_forge_lint!( SCREAMING_SNAKE_CASE_CONSTANT, Severity::Info, "screaming-snake-case-const", - "constants should use SCREAMING_SNAKE_CASE", - "https://docs.soliditylang.org/en/latest/style-guide.html#constants" + "constants should use SCREAMING_SNAKE_CASE" ); declare_forge_lint!( diff --git a/crates/lint/src/sol/macros.rs b/crates/lint/src/sol/macros.rs index 093b96a7e4a70..357f742aa297c 100644 --- a/crates/lint/src/sol/macros.rs +++ b/crates/lint/src/sol/macros.rs @@ -7,16 +7,20 @@ /// - `$severity`: The `Severity` of the lint (e.g. `High`, `Med`, `Low`, `Info`, `Gas`). /// - `$str_id`: A unique identifier used to reference a specific lint during configuration. /// - `$desc`: A short description of the lint. -/// - `$help` (optional): Link to additional information about the lint or best practices. +/// +/// # Note +/// Each lint must have a `help` section in the foundry book. This help field is auto-generated by +/// the macro. Because of that, to ensure that new lint rules have their corresponding docs in the +/// book, the existence of the lint rule's help section is validated with a unit test. #[macro_export] macro_rules! declare_forge_lint { - ($id:ident, $severity:expr, $str_id:expr, $desc:expr, $help:expr) => { + ($id:ident, $severity:expr, $str_id:expr, $desc:expr) => { // Declare the static `Lint` metadata pub static $id: SolLint = SolLint { id: $str_id, severity: $severity, description: $desc, - help: if $help.is_empty() { None } else { Some($help) }, + help: concat!("https://book.getfoundry.sh/reference/forge/forge-lint#", $str_id), }; }; diff --git a/crates/lint/src/sol/med/div_mul.rs b/crates/lint/src/sol/med/div_mul.rs index b513468be6b83..b154971e55434 100644 --- a/crates/lint/src/sol/med/div_mul.rs +++ b/crates/lint/src/sol/med/div_mul.rs @@ -10,8 +10,7 @@ declare_forge_lint!( DIVIDE_BEFORE_MULTIPLY, Severity::Med, "divide-before-multiply", - "multiplication should occur before division to avoid loss of precision", - "" + "multiplication should occur before division to avoid loss of precision" ); impl<'ast> EarlyLintPass<'ast> for DivideBeforeMultiply { diff --git a/crates/lint/src/sol/mod.rs b/crates/lint/src/sol/mod.rs index 6bb2ffabef39a..463777d5b194a 100644 --- a/crates/lint/src/sol/mod.rs +++ b/crates/lint/src/sol/mod.rs @@ -159,7 +159,7 @@ pub enum SolLintError { pub struct SolLint { id: &'static str, description: &'static str, - help: Option<&'static str>, + help: &'static str, severity: Severity, } @@ -173,7 +173,7 @@ impl Lint for SolLint { fn description(&self) -> &'static str { self.description } - fn help(&self) -> Option<&'static str> { + fn help(&self) -> &'static str { self.help } } diff --git a/crates/lint/testdata/DivideBeforeMultiply.stderr b/crates/lint/testdata/DivideBeforeMultiply.stderr index 08d8ebe25d1c9..1c98f4b13d194 100644 --- a/crates/lint/testdata/DivideBeforeMultiply.stderr +++ b/crates/lint/testdata/DivideBeforeMultiply.stderr @@ -4,6 +4,7 @@ warning[divide-before-multiply]: multiplication should occur before division to 3 | (1 / 2) * 3; | ----------- | + = help: https://book.getfoundry.sh/reference/forge/forge-lint#divide-before-multiply warning[divide-before-multiply]: multiplication should occur before division to avoid loss of precision --> ROOT/testdata/DivideBeforeMultiply.sol:LL:CC @@ -11,6 +12,7 @@ warning[divide-before-multiply]: multiplication should occur before division to 5 | ((1 / 2) * 3) * 4; | ----------- | + = help: https://book.getfoundry.sh/reference/forge/forge-lint#divide-before-multiply warning[divide-before-multiply]: multiplication should occur before division to avoid loss of precision --> ROOT/testdata/DivideBeforeMultiply.sol:LL:CC @@ -18,6 +20,7 @@ warning[divide-before-multiply]: multiplication should occur before division to 6 | ((1 * 2) / 3) * 4; | ----------------- | + = help: https://book.getfoundry.sh/reference/forge/forge-lint#divide-before-multiply warning[divide-before-multiply]: multiplication should occur before division to avoid loss of precision --> ROOT/testdata/DivideBeforeMultiply.sol:LL:CC @@ -25,6 +28,7 @@ warning[divide-before-multiply]: multiplication should occur before division to 7 | (1 / 2 / 3) * 4; | --------------- | + = help: https://book.getfoundry.sh/reference/forge/forge-lint#divide-before-multiply warning[divide-before-multiply]: multiplication should occur before division to avoid loss of precision --> ROOT/testdata/DivideBeforeMultiply.sol:LL:CC @@ -32,6 +36,7 @@ warning[divide-before-multiply]: multiplication should occur before division to 8 | (1 / (2 + 3)) * 4; | ----------------- | + = help: https://book.getfoundry.sh/reference/forge/forge-lint#divide-before-multiply warning[divide-before-multiply]: multiplication should occur before division to avoid loss of precision --> ROOT/testdata/DivideBeforeMultiply.sol:LL:CC @@ -39,4 +44,5 @@ warning[divide-before-multiply]: multiplication should occur before division to 15 | 1 / ((2 / 3) * 3); | ----------- | + = help: https://book.getfoundry.sh/reference/forge/forge-lint#divide-before-multiply diff --git a/crates/lint/testdata/IncorrectShift.stderr b/crates/lint/testdata/IncorrectShift.stderr index 16fbda627cd9b..46276262da4bd 100644 --- a/crates/lint/testdata/IncorrectShift.stderr +++ b/crates/lint/testdata/IncorrectShift.stderr @@ -4,6 +4,7 @@ warning[incorrect-shift]: the order of args in a shift operation is incorrect 21 | result = 2 << stateValue; | --------------- | + = help: https://book.getfoundry.sh/reference/forge/forge-lint#incorrect-shift warning[incorrect-shift]: the order of args in a shift operation is incorrect --> ROOT/testdata/IncorrectShift.sol:LL:CC @@ -11,6 +12,7 @@ warning[incorrect-shift]: the order of args in a shift operation is incorrect 22 | result = 8 >> localValue; | --------------- | + = help: https://book.getfoundry.sh/reference/forge/forge-lint#incorrect-shift warning[incorrect-shift]: the order of args in a shift operation is incorrect --> ROOT/testdata/IncorrectShift.sol:LL:CC @@ -18,6 +20,7 @@ warning[incorrect-shift]: the order of args in a shift operation is incorrect 23 | result = 16 << (stateValue + 1); | ---------------------- | + = help: https://book.getfoundry.sh/reference/forge/forge-lint#incorrect-shift warning[incorrect-shift]: the order of args in a shift operation is incorrect --> ROOT/testdata/IncorrectShift.sol:LL:CC @@ -25,6 +28,7 @@ warning[incorrect-shift]: the order of args in a shift operation is incorrect 24 | result = 32 >> getAmount(); | ----------------- | + = help: https://book.getfoundry.sh/reference/forge/forge-lint#incorrect-shift warning[incorrect-shift]: the order of args in a shift operation is incorrect --> ROOT/testdata/IncorrectShift.sol:LL:CC @@ -32,4 +36,5 @@ warning[incorrect-shift]: the order of args in a shift operation is incorrect 25 | ... result = 1 << (localValue > 10 ? localShiftAmount : stateShiftAmount); | ------------------------------------------------------------ | + = help: https://book.getfoundry.sh/reference/forge/forge-lint#incorrect-shift diff --git a/crates/lint/testdata/Keccak256.stderr b/crates/lint/testdata/Keccak256.stderr index e589bec00eb77..8011afa89a112 100644 --- a/crates/lint/testdata/Keccak256.stderr +++ b/crates/lint/testdata/Keccak256.stderr @@ -4,6 +4,7 @@ note[asm-keccak256]: hash using inline assembly to save gas 3 | keccak256(abi.encodePacked(a, b)); | --------- | + = help: https://book.getfoundry.sh/reference/forge/forge-lint#asm-keccak256 note[asm-keccak256]: hash using inline assembly to save gas --> ROOT/testdata/Keccak256.sol:LL:CC @@ -11,4 +12,5 @@ note[asm-keccak256]: hash using inline assembly to save gas 7 | keccak256(abi.encodePacked(a, b)); | --------- | + = help: https://book.getfoundry.sh/reference/forge/forge-lint#asm-keccak256 diff --git a/crates/lint/testdata/MixedCase.stderr b/crates/lint/testdata/MixedCase.stderr index 1245d53caf5cc..0976dced8716c 100644 --- a/crates/lint/testdata/MixedCase.stderr +++ b/crates/lint/testdata/MixedCase.stderr @@ -4,6 +4,7 @@ note[mixed-case-variable]: mutable variables should use mixedCase 9 | uint256 Variablemixedcase; | ----------------- | + = help: https://book.getfoundry.sh/reference/forge/forge-lint#mixed-case-variable note[mixed-case-variable]: mutable variables should use mixedCase --> ROOT/testdata/MixedCase.sol:LL:CC @@ -11,6 +12,7 @@ note[mixed-case-variable]: mutable variables should use mixedCase 10 | uint256 VARIABLE_MIXED_CASE; | ------------------- | + = help: https://book.getfoundry.sh/reference/forge/forge-lint#mixed-case-variable note[mixed-case-variable]: mutable variables should use mixedCase --> ROOT/testdata/MixedCase.sol:LL:CC @@ -18,6 +20,7 @@ note[mixed-case-variable]: mutable variables should use mixedCase 11 | uint256 VariableMixedCase; | ----------------- | + = help: https://book.getfoundry.sh/reference/forge/forge-lint#mixed-case-variable note[mixed-case-variable]: mutable variables should use mixedCase --> ROOT/testdata/MixedCase.sol:LL:CC @@ -25,6 +28,7 @@ note[mixed-case-variable]: mutable variables should use mixedCase 17 | uint256 testVAL; | ------- | + = help: https://book.getfoundry.sh/reference/forge/forge-lint#mixed-case-variable note[mixed-case-variable]: mutable variables should use mixedCase --> ROOT/testdata/MixedCase.sol:LL:CC @@ -32,6 +36,7 @@ note[mixed-case-variable]: mutable variables should use mixedCase 18 | uint256 TestVal; | ------- | + = help: https://book.getfoundry.sh/reference/forge/forge-lint#mixed-case-variable note[mixed-case-variable]: mutable variables should use mixedCase --> ROOT/testdata/MixedCase.sol:LL:CC @@ -39,6 +44,7 @@ note[mixed-case-variable]: mutable variables should use mixedCase 19 | uint256 TESTVAL; | ------- | + = help: https://book.getfoundry.sh/reference/forge/forge-lint#mixed-case-variable note[mixed-case-function]: function names should use mixedCase --> ROOT/testdata/MixedCase.sol:LL:CC @@ -46,7 +52,7 @@ note[mixed-case-function]: function names should use mixedCase 26 | function Functionmixedcase() public {} | ----------------- | - = help: https://docs.soliditylang.org/en/latest/style-guide.html#function-names + = help: https://book.getfoundry.sh/reference/forge/forge-lint#mixed-case-function note[mixed-case-function]: function names should use mixedCase --> ROOT/testdata/MixedCase.sol:LL:CC @@ -54,7 +60,7 @@ note[mixed-case-function]: function names should use mixedCase 27 | function FUNCTION_MIXED_CASE() public {} | ------------------- | - = help: https://docs.soliditylang.org/en/latest/style-guide.html#function-names + = help: https://book.getfoundry.sh/reference/forge/forge-lint#mixed-case-function note[mixed-case-function]: function names should use mixedCase --> ROOT/testdata/MixedCase.sol:LL:CC @@ -62,7 +68,7 @@ note[mixed-case-function]: function names should use mixedCase 28 | function FunctionMixedCase() public {} | ----------------- | - = help: https://docs.soliditylang.org/en/latest/style-guide.html#function-names + = help: https://book.getfoundry.sh/reference/forge/forge-lint#mixed-case-function note[mixed-case-function]: function names should use mixedCase --> ROOT/testdata/MixedCase.sol:LL:CC @@ -70,7 +76,7 @@ note[mixed-case-function]: function names should use mixedCase 29 | function function_mixed_case() public {} | ------------------- | - = help: https://docs.soliditylang.org/en/latest/style-guide.html#function-names + = help: https://book.getfoundry.sh/reference/forge/forge-lint#mixed-case-function note[mixed-case-function]: function names should use mixedCase --> ROOT/testdata/MixedCase.sol:LL:CC @@ -78,7 +84,7 @@ note[mixed-case-function]: function names should use mixedCase 53 | function invariantBalance_MixedCase_Enabled() public {} | ---------------------------------- | - = help: https://docs.soliditylang.org/en/latest/style-guide.html#function-names + = help: https://book.getfoundry.sh/reference/forge/forge-lint#mixed-case-function note[mixed-case-function]: function names should use mixedCase --> ROOT/testdata/MixedCase.sol:LL:CC @@ -86,5 +92,5 @@ note[mixed-case-function]: function names should use mixedCase 54 | function invariantbalance_mixedcase_enabled() public {} | ---------------------------------- | - = help: https://docs.soliditylang.org/en/latest/style-guide.html#function-names + = help: https://book.getfoundry.sh/reference/forge/forge-lint#mixed-case-function diff --git a/crates/lint/testdata/ScreamingSnakeCase.stderr b/crates/lint/testdata/ScreamingSnakeCase.stderr index 96c2cb34405b3..b511f09d254f3 100644 --- a/crates/lint/testdata/ScreamingSnakeCase.stderr +++ b/crates/lint/testdata/ScreamingSnakeCase.stderr @@ -4,7 +4,7 @@ note[screaming-snake-case-const]: constants should use SCREAMING_SNAKE_CASE 9 | uint256 constant screamingSnakeCase = 0; | ------------------ | - = help: https://docs.soliditylang.org/en/latest/style-guide.html#constants + = help: https://book.getfoundry.sh/reference/forge/forge-lint#screaming-snake-case-const note[screaming-snake-case-const]: constants should use SCREAMING_SNAKE_CASE --> ROOT/testdata/ScreamingSnakeCase.sol:LL:CC @@ -12,7 +12,7 @@ note[screaming-snake-case-const]: constants should use SCREAMING_SNAKE_CASE 10 | uint256 constant screaming_snake_case = 0; | -------------------- | - = help: https://docs.soliditylang.org/en/latest/style-guide.html#constants + = help: https://book.getfoundry.sh/reference/forge/forge-lint#screaming-snake-case-const note[screaming-snake-case-const]: constants should use SCREAMING_SNAKE_CASE --> ROOT/testdata/ScreamingSnakeCase.sol:LL:CC @@ -20,7 +20,7 @@ note[screaming-snake-case-const]: constants should use SCREAMING_SNAKE_CASE 11 | uint256 constant ScreamingSnakeCase = 0; | ------------------ | - = help: https://docs.soliditylang.org/en/latest/style-guide.html#constants + = help: https://book.getfoundry.sh/reference/forge/forge-lint#screaming-snake-case-const note[screaming-snake-case-const]: constants should use SCREAMING_SNAKE_CASE --> ROOT/testdata/ScreamingSnakeCase.sol:LL:CC @@ -28,7 +28,7 @@ note[screaming-snake-case-const]: constants should use SCREAMING_SNAKE_CASE 12 | uint256 constant SCREAMING_snake_case = 0; | -------------------- | - = help: https://docs.soliditylang.org/en/latest/style-guide.html#constants + = help: https://book.getfoundry.sh/reference/forge/forge-lint#screaming-snake-case-const note[screaming-snake-case-immutable]: immutables should use SCREAMING_SNAKE_CASE --> ROOT/testdata/ScreamingSnakeCase.sol:LL:CC @@ -36,6 +36,7 @@ note[screaming-snake-case-immutable]: immutables should use SCREAMING_SNAKE_CASE 19 | uint256 immutable screamingSnakeCase0 = 0; | ------------------- | + = help: https://book.getfoundry.sh/reference/forge/forge-lint#screaming-snake-case-immutable note[screaming-snake-case-immutable]: immutables should use SCREAMING_SNAKE_CASE --> ROOT/testdata/ScreamingSnakeCase.sol:LL:CC @@ -43,6 +44,7 @@ note[screaming-snake-case-immutable]: immutables should use SCREAMING_SNAKE_CASE 20 | uint256 immutable screaming_snake_case0 = 0; | --------------------- | + = help: https://book.getfoundry.sh/reference/forge/forge-lint#screaming-snake-case-immutable note[screaming-snake-case-immutable]: immutables should use SCREAMING_SNAKE_CASE --> ROOT/testdata/ScreamingSnakeCase.sol:LL:CC @@ -50,6 +52,7 @@ note[screaming-snake-case-immutable]: immutables should use SCREAMING_SNAKE_CASE 21 | uint256 immutable ScreamingSnakeCase0 = 0; | ------------------- | + = help: https://book.getfoundry.sh/reference/forge/forge-lint#screaming-snake-case-immutable note[screaming-snake-case-immutable]: immutables should use SCREAMING_SNAKE_CASE --> ROOT/testdata/ScreamingSnakeCase.sol:LL:CC @@ -57,4 +60,5 @@ note[screaming-snake-case-immutable]: immutables should use SCREAMING_SNAKE_CASE 22 | uint256 immutable SCREAMING_snake_case_0 = 0; | ---------------------- | + = help: https://book.getfoundry.sh/reference/forge/forge-lint#screaming-snake-case-immutable diff --git a/crates/lint/testdata/StructPascalCase.stderr b/crates/lint/testdata/StructPascalCase.stderr index 2ef869c7ccc21..7858c18cbf33d 100644 --- a/crates/lint/testdata/StructPascalCase.stderr +++ b/crates/lint/testdata/StructPascalCase.stderr @@ -4,7 +4,7 @@ note[pascal-case-struct]: structs should use PascalCase 13 | struct _PascalCase { | ----------- | - = help: https://docs.soliditylang.org/en/latest/style-guide.html#struct-names + = help: https://book.getfoundry.sh/reference/forge/forge-lint#pascal-case-struct note[pascal-case-struct]: structs should use PascalCase --> ROOT/testdata/StructPascalCase.sol:LL:CC @@ -12,7 +12,7 @@ note[pascal-case-struct]: structs should use PascalCase 17 | struct pascalCase { | ---------- | - = help: https://docs.soliditylang.org/en/latest/style-guide.html#struct-names + = help: https://book.getfoundry.sh/reference/forge/forge-lint#pascal-case-struct note[pascal-case-struct]: structs should use PascalCase --> ROOT/testdata/StructPascalCase.sol:LL:CC @@ -20,7 +20,7 @@ note[pascal-case-struct]: structs should use PascalCase 21 | struct pascalcase { | ---------- | - = help: https://docs.soliditylang.org/en/latest/style-guide.html#struct-names + = help: https://book.getfoundry.sh/reference/forge/forge-lint#pascal-case-struct note[pascal-case-struct]: structs should use PascalCase --> ROOT/testdata/StructPascalCase.sol:LL:CC @@ -28,7 +28,7 @@ note[pascal-case-struct]: structs should use PascalCase 25 | struct pascal_case { | ----------- | - = help: https://docs.soliditylang.org/en/latest/style-guide.html#struct-names + = help: https://book.getfoundry.sh/reference/forge/forge-lint#pascal-case-struct note[pascal-case-struct]: structs should use PascalCase --> ROOT/testdata/StructPascalCase.sol:LL:CC @@ -36,7 +36,7 @@ note[pascal-case-struct]: structs should use PascalCase 29 | struct PASCAL_CASE { | ----------- | - = help: https://docs.soliditylang.org/en/latest/style-guide.html#struct-names + = help: https://book.getfoundry.sh/reference/forge/forge-lint#pascal-case-struct note[pascal-case-struct]: structs should use PascalCase --> ROOT/testdata/StructPascalCase.sol:LL:CC @@ -44,5 +44,5 @@ note[pascal-case-struct]: structs should use PascalCase 33 | struct PASCALCASE { | ---------- | - = help: https://docs.soliditylang.org/en/latest/style-guide.html#struct-names + = help: https://book.getfoundry.sh/reference/forge/forge-lint#pascal-case-struct From ca03f8ffe74d56f559ad861e2eea911f19d5b906 Mon Sep 17 00:00:00 2001 From: Mablr <59505383+mablr@users.noreply.github.com> Date: Tue, 27 May 2025 00:33:22 +0200 Subject: [PATCH 046/232] feat(cast mktx): add support for "--ethsign" option (#10641) - Sign transactions using "eth_signTransaction" on local node with unlocked accounts. - Same TX building logic as in "cast send --unlocked". - Added a test case to validate the new functionality. --- crates/cast/src/cmd/mktx.rs | 22 +++++++++++++++++++--- crates/cast/tests/cli/main.rs | 31 +++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/crates/cast/src/cmd/mktx.rs b/crates/cast/src/cmd/mktx.rs index af06d556c23ff..ebfb5afeadd47 100644 --- a/crates/cast/src/cmd/mktx.rs +++ b/crates/cast/src/cmd/mktx.rs @@ -2,6 +2,7 @@ use crate::tx::{self, CastTxBuilder}; use alloy_ens::NameOrAddress; use alloy_network::{eip2718::Encodable2718, EthereumWallet, TransactionBuilder}; use alloy_primitives::hex; +use alloy_provider::Provider; use alloy_signer::Signer; use clap::Parser; use eyre::{OptionExt, Result}; @@ -50,6 +51,10 @@ pub struct MakeTxArgs { /// Relaxes the wallet requirement. #[arg(long, requires = "from")] raw_unsigned: bool, + + /// Call `eth_signTransaction` using the `--from` argument or $ETH_FROM as sender + #[arg(long, requires = "from", conflicts_with = "raw_unsigned")] + ethsign: bool, } #[derive(Debug, Parser)] @@ -70,7 +75,7 @@ pub enum MakeTxSubcommands { impl MakeTxArgs { pub async fn run(self) -> Result<()> { - let Self { to, mut sig, mut args, command, tx, path, eth, raw_unsigned } = self; + let Self { to, mut sig, mut args, command, tx, path, eth, raw_unsigned, ethsign } = self; let blob_data = if let Some(path) = path { Some(std::fs::read(path)?) } else { None }; @@ -91,7 +96,7 @@ impl MakeTxArgs { let provider = get_provider(&config)?; - let tx_builder = CastTxBuilder::new(provider, tx, &config) + let tx_builder = CastTxBuilder::new(&provider, tx, &config) .await? .with_to(to) .await? @@ -108,7 +113,18 @@ impl MakeTxArgs { return Ok(()); } - // Retrieve the signer, and bail if it can't be constructed. + if ethsign { + // Use "eth_signTransaction" to sign the transaction only works if the node/RPC has + // unlocked accounts. + let (tx, _) = tx_builder.build(config.sender).await?; + let signed_tx = provider.sign_transaction(tx).await?; + + sh_println!("{signed_tx}")?; + return Ok(()); + } + + // Default to using the local signer. + // Get the signer from the wallet, and fail if it can't be constructed. let signer = eth.wallet.signer().await?; let from = signer.address(); diff --git a/crates/cast/tests/cli/main.rs b/crates/cast/tests/cli/main.rs index 4735a8ce1abbc..1a0c0bf958cf8 100644 --- a/crates/cast/tests/cli/main.rs +++ b/crates/cast/tests/cli/main.rs @@ -1296,6 +1296,37 @@ casttest!(mktx_raw_unsigned, |_prj, cmd| { ]]); }); +casttest!(mktx_ethsign, async |_prj, cmd| { + let (_api, handle) = anvil::spawn(NodeConfig::test()).await; + let rpc = handle.http_endpoint(); + cmd.args([ + "mktx", + "--from", + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "--chain", + "31337", + "--nonce", + "0", + "--gas-limit", + "21000", + "--gas-price", + "10000000000", + "--priority-gas-price", + "1000000000", + "0x0000000000000000000000000000000000000001", + "--ethsign", + "--rpc-url", + rpc.as_str(), + ]) + .assert_success() + .stdout_eq(str![[ + r#" +0x02f86d827a6980843b9aca008502540be4008252089400000000000000000000000000000000000000018080c001a0b8eeb1ded87b085859c510c5692bed231e3ee8b068ccf71142bbf28da0e95987a07813b676a248ae8055f28495021d78dee6695479d339a6ad9d260d9eaf20674c + +"# + ]]); +}); + // tests that the raw encoded transaction is returned casttest!(tx_raw, |_prj, cmd| { let rpc = next_http_rpc_endpoint(); From fbb793c5383503b7aa0c037e510690ae1d17f5e2 Mon Sep 17 00:00:00 2001 From: Mablr <59505383+mablr@users.noreply.github.com> Date: Tue, 27 May 2025 16:28:39 +0200 Subject: [PATCH 047/232] chore(wallets): improve error message for signer instantiation failure (#10646) chore(wallets): improve error message on signer instantiation failure --- crates/wallets/src/wallet.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/crates/wallets/src/wallet.rs b/crates/wallets/src/wallet.rs index 29ce54438586d..8e3a4dafb332a 100644 --- a/crates/wallets/src/wallet.rs +++ b/crates/wallets/src/wallet.rs @@ -128,12 +128,14 @@ impl WalletOpts { eyre::bail!( "\ Error accessing local wallet. Did you set a private key, mnemonic or keystore? -Run `cast send --help` or `forge create --help` and use the corresponding CLI +Run the command with --help flag for more information or use the corresponding CLI flag to set your key via: --private-key, --mnemonic-path, --aws, --gcp, --interactive, --trezor or --ledger. -Alternatively, if you're using a local node with unlocked accounts, -use the --unlocked flag and either set the `ETH_FROM` environment variable to the address -of the unlocked account you want to use, or provide the --from flag with the address directly." +Alternatively, when using the `cast send` or `cast mktx` commands with a local node +or RPC that has unlocked accounts, the --unlocked or --ethsign flags can be used, +respectively. The sender address can be specified by setting the `ETH_FROM` environment +variable to the desired unlocked account address, or by providing the address directly +using the --from flag." ) }; From fbdec00058201cf794b5e148de8d6807a033af21 Mon Sep 17 00:00:00 2001 From: Ishika Choudhury <117741714+Rimeeeeee@users.noreply.github.com> Date: Tue, 27 May 2025 20:19:41 +0530 Subject: [PATCH 048/232] chore: replaced anvil hardforks with alloy hardforks (#10612) * chore: replaced anvil hardforks with alloy hardforks * fixes * fixes * fixes * removed redundant op and alloy hardforks enum * fixes * fixes * bumped alloy hardforks and kept default to prague and isthmus * bumped alloy-hardforks and fixes --------- Co-authored-by: zerosnacks <95942363+zerosnacks@users.noreply.github.com> --- Cargo.lock | 12 +- Cargo.toml | 2 + crates/anvil/Cargo.toml | 2 + crates/anvil/src/cmd.rs | 7 +- crates/anvil/src/config.rs | 15 +- crates/anvil/src/hardfork.rs | 274 ++++++++------------------- crates/anvil/src/lib.rs | 3 +- crates/anvil/tests/it/anvil.rs | 3 +- crates/anvil/tests/it/anvil_api.rs | 3 +- crates/anvil/tests/it/eip4844.rs | 3 +- crates/anvil/tests/it/eip7702.rs | 3 +- crates/anvil/tests/it/otterscan.rs | 3 +- crates/anvil/tests/it/traces.rs | 3 +- crates/anvil/tests/it/transaction.rs | 3 +- crates/cast/Cargo.toml | 1 + crates/cast/tests/cli/main.rs | 3 +- crates/forge/Cargo.toml | 1 + crates/forge/tests/cli/script.rs | 3 +- 18 files changed, 126 insertions(+), 218 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c05a8b99f5d05..1fa7e6a150282 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -253,9 +253,9 @@ dependencies = [ [[package]] name = "alloy-hardforks" -version = "0.2.3" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6b8067561eb8f884b215ace4c962313c5467e47bde6b457c8c51e268fb5d99" +checksum = "fbff8445282ec080c2673692062bd4930d7a0d6bda257caf138cfc650c503000" dependencies = [ "alloy-chains", "alloy-eip2124", @@ -348,9 +348,9 @@ dependencies = [ [[package]] name = "alloy-op-hardforks" -version = "0.2.3" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08043c9284e597f9b5cf741cc6d906fdb26c195a01d88423c84c00ffda835713" +checksum = "9ddfbb5cc9f614efa5d56e0d7226214bb67b29271d44b6ddfcbbe25eb0ff898b" dependencies = [ "alloy-hardforks", "auto_impl", @@ -1023,8 +1023,10 @@ dependencies = [ "alloy-eips", "alloy-evm", "alloy-genesis", + "alloy-hardforks", "alloy-network", "alloy-op-evm", + "alloy-op-hardforks", "alloy-primitives", "alloy-provider", "alloy-pubsub", @@ -2351,6 +2353,7 @@ dependencies = [ "alloy-contract", "alloy-dyn-abi", "alloy-ens", + "alloy-hardforks", "alloy-json-abi", "alloy-json-rpc", "alloy-network", @@ -3778,6 +3781,7 @@ version = "1.2.1" dependencies = [ "alloy-chains", "alloy-dyn-abi", + "alloy-hardforks", "alloy-json-abi", "alloy-network", "alloy-primitives", diff --git a/Cargo.toml b/Cargo.toml index 8686f046c2c14..3baefd5dca836 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -230,6 +230,8 @@ alloy-transport = { version = "1.0.7", default-features = false } alloy-transport-http = { version = "1.0.7", default-features = false } alloy-transport-ipc = { version = "1.0.7", default-features = false } alloy-transport-ws = { version = "1.0.7", default-features = false } +alloy-hardforks = { version = "0.2.6", default-features = false } +alloy-op-hardforks = { version = "0.2.6", default-features = false } ## alloy-core alloy-dyn-abi = "1.0" diff --git a/crates/anvil/Cargo.toml b/crates/anvil/Cargo.toml index e45c95e49f85e..23ff53b271895 100644 --- a/crates/anvil/Cargo.toml +++ b/crates/anvil/Cargo.toml @@ -55,6 +55,8 @@ alloy-transport.workspace = true alloy-chains.workspace = true alloy-genesis.workspace = true alloy-trie.workspace = true +alloy-hardforks.workspace = true +alloy-op-hardforks.workspace = true op-alloy-consensus = { workspace = true, features = ["serde"] } # revm diff --git a/crates/anvil/src/cmd.rs b/crates/anvil/src/cmd.rs index d4b91e14f20fd..c8223a76ed959 100644 --- a/crates/anvil/src/cmd.rs +++ b/crates/anvil/src/cmd.rs @@ -1,9 +1,10 @@ use crate::{ config::{ForkChoice, DEFAULT_MNEMONIC}, eth::{backend::db::SerializableState, pool::transactions::TransactionOrder, EthApi}, - AccountGenerator, EthereumHardfork, NodeConfig, OptimismHardfork, CHAIN_ID, + AccountGenerator, EthereumHardfork, NodeConfig, CHAIN_ID, }; use alloy_genesis::Genesis; +use alloy_op_hardforks::OpHardfork; use alloy_primitives::{utils::Unit, B256, U256}; use alloy_signer_local::coins_bip39::{English, Mnemonic}; use anvil_server::ServerConfig; @@ -218,7 +219,7 @@ impl NodeArgs { let hardfork = match &self.hardfork { Some(hf) => { if self.evm.optimism { - Some(OptimismHardfork::from_str(hf)?.into()) + Some(OpHardfork::from_str(hf)?.into()) } else { Some(EthereumHardfork::from_str(hf)?.into()) } @@ -836,7 +837,7 @@ mod tests { let args: NodeArgs = NodeArgs::parse_from(["anvil", "--optimism", "--hardfork", "Regolith"]); let config = args.into_node_config().unwrap(); - assert_eq!(config.hardfork, Some(OptimismHardfork::Regolith.into())); + assert_eq!(config.hardfork, Some(OpHardfork::Regolith.into())); } #[test] diff --git a/crates/anvil/src/config.rs b/crates/anvil/src/config.rs index 722408c72a9c4..1cde743c3e952 100644 --- a/crates/anvil/src/config.rs +++ b/crates/anvil/src/config.rs @@ -11,13 +11,14 @@ use crate::{ fees::{INITIAL_BASE_FEE, INITIAL_GAS_PRICE}, pool::transactions::{PoolTransaction, TransactionOrder}, }, - hardfork::ChainHardfork, + hardfork::{ethereum_hardfork_from_block_tag, spec_id_from_ethereum_hardfork, ChainHardfork}, mem::{self, in_memory_db::MemDb}, - EthereumHardfork, FeeManager, OptimismHardfork, PrecompileFactory, + EthereumHardfork, FeeManager, PrecompileFactory, }; use alloy_consensus::BlockHeader; use alloy_genesis::Genesis; use alloy_network::{AnyNetwork, TransactionResponse}; +use alloy_op_hardforks::OpHardfork; use alloy_primitives::{hex, map::HashMap, utils::Unit, BlockNumber, TxHash, U256}; use alloy_provider::Provider; use alloy_rpc_types::{Block, BlockNumberOrTag}; @@ -530,9 +531,9 @@ impl NodeConfig { return hardfork; } if self.enable_optimism { - return OptimismHardfork::default().into(); + return OpHardfork::Isthmus.into(); } - EthereumHardfork::default().into() + EthereumHardfork::Cancun.into() } /// Sets a custom code size limit @@ -1186,8 +1187,10 @@ impl NodeConfig { let chain_id = provider.get_chain_id().await.wrap_err("failed to fetch network chain ID")?; if alloy_chains::NamedChain::Mainnet == chain_id { - let hardfork: EthereumHardfork = fork_block_number.into(); - env.evm_env.cfg_env.spec = hardfork.into(); + let hardfork: EthereumHardfork = + ethereum_hardfork_from_block_tag(fork_block_number); + + env.evm_env.cfg_env.spec = spec_id_from_ethereum_hardfork(hardfork); self.hardfork = Some(ChainHardfork::Ethereum(hardfork)); } Some(U256::from(chain_id)) diff --git a/crates/anvil/src/hardfork.rs b/crates/anvil/src/hardfork.rs index 34fe97fa1de41..f5e063aafc625 100644 --- a/crates/anvil/src/hardfork.rs +++ b/crates/anvil/src/hardfork.rs @@ -1,14 +1,14 @@ -use std::str::FromStr; - +use alloy_hardforks::EthereumHardfork; +use alloy_op_hardforks::OpHardfork::{self}; use alloy_rpc_types::BlockNumberOrTag; -use eyre::bail; + use op_revm::OpSpecId; use revm::primitives::hardfork::SpecId; #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum ChainHardfork { Ethereum(EthereumHardfork), - Optimism(OptimismHardfork), + Optimism(OpHardfork), } impl From for ChainHardfork { @@ -17,8 +17,8 @@ impl From for ChainHardfork { } } -impl From for ChainHardfork { - fn from(value: OptimismHardfork) -> Self { +impl From for ChainHardfork { + fn from(value: OpHardfork) -> Self { Self::Optimism(value) } } @@ -26,213 +26,99 @@ impl From for ChainHardfork { impl From for SpecId { fn from(fork: ChainHardfork) -> Self { match fork { - ChainHardfork::Ethereum(hardfork) => hardfork.into(), - ChainHardfork::Optimism(hardfork) => hardfork.into_eth_spec(), - } - } -} - -#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub enum EthereumHardfork { - Frontier, - Homestead, - Dao, - Tangerine, - SpuriousDragon, - Byzantium, - Constantinople, - Petersburg, - Istanbul, - Muirglacier, - Berlin, - London, - ArrowGlacier, - GrayGlacier, - Paris, - Shanghai, - Cancun, - Prague, - #[default] - Latest, -} - -impl EthereumHardfork { - /// Get the first block number of the hardfork. - pub fn fork_block(&self) -> u64 { - match *self { - Self::Frontier => 0, - Self::Homestead => 1150000, - Self::Dao => 1920000, - Self::Tangerine => 2463000, - Self::SpuriousDragon => 2675000, - Self::Byzantium => 4370000, - Self::Constantinople | Self::Petersburg => 7280000, - Self::Istanbul => 9069000, - Self::Muirglacier => 9200000, - Self::Berlin => 12244000, - Self::London => 12965000, - Self::ArrowGlacier => 13773000, - Self::GrayGlacier => 15050000, - Self::Paris => 15537394, - Self::Shanghai => 17034870, - Self::Cancun | Self::Latest => 19426587, - Self::Prague => 22431084, + ChainHardfork::Ethereum(hardfork) => spec_id_from_ethereum_hardfork(hardfork), + ChainHardfork::Optimism(hardfork) => spec_id_from_optimism_hardfork(hardfork).into(), } } } -impl FromStr for EthereumHardfork { - type Err = eyre::Report; - - fn from_str(s: &str) -> Result { - let s = s.to_lowercase(); - let hardfork = match s.as_str() { - "frontier" | "1" => Self::Frontier, - "homestead" | "2" => Self::Homestead, - "dao" | "3" => Self::Dao, - "tangerine" | "4" => Self::Tangerine, - "spuriousdragon" | "5" => Self::SpuriousDragon, - "byzantium" | "6" => Self::Byzantium, - "constantinople" | "7" => Self::Constantinople, - "petersburg" | "8" => Self::Petersburg, - "istanbul" | "9" => Self::Istanbul, - "muirglacier" | "10" => Self::Muirglacier, - "berlin" | "11" => Self::Berlin, - "london" | "12" => Self::London, - "arrowglacier" | "13" => Self::ArrowGlacier, - "grayglacier" | "14" => Self::GrayGlacier, - "paris" | "merge" | "15" => Self::Paris, - "shanghai" | "16" => Self::Shanghai, - "cancun" | "17" => Self::Cancun, - "prague" | "18" => Self::Prague, - "latest" => Self::Latest, - _ => bail!("Unknown hardfork {s}"), - }; - Ok(hardfork) +/// Map an EthereumHardfork enum into its corresponding SpecId. +pub fn spec_id_from_ethereum_hardfork(hardfork: EthereumHardfork) -> SpecId { + match hardfork { + EthereumHardfork::Frontier => SpecId::FRONTIER, + EthereumHardfork::Homestead => SpecId::HOMESTEAD, + EthereumHardfork::Dao => SpecId::DAO_FORK, + EthereumHardfork::Tangerine => SpecId::TANGERINE, + EthereumHardfork::SpuriousDragon => SpecId::SPURIOUS_DRAGON, + EthereumHardfork::Byzantium => SpecId::BYZANTIUM, + EthereumHardfork::Constantinople => SpecId::CONSTANTINOPLE, + EthereumHardfork::Petersburg => SpecId::PETERSBURG, + EthereumHardfork::Istanbul => SpecId::ISTANBUL, + EthereumHardfork::MuirGlacier => SpecId::MUIR_GLACIER, + EthereumHardfork::Berlin => SpecId::BERLIN, + EthereumHardfork::London => SpecId::LONDON, + EthereumHardfork::ArrowGlacier => SpecId::ARROW_GLACIER, + EthereumHardfork::GrayGlacier => SpecId::GRAY_GLACIER, + EthereumHardfork::Paris => SpecId::MERGE, + EthereumHardfork::Shanghai => SpecId::SHANGHAI, + EthereumHardfork::Cancun => SpecId::CANCUN, + EthereumHardfork::Prague => SpecId::PRAGUE, + EthereumHardfork::Osaka => SpecId::OSAKA, } } -impl From for SpecId { - fn from(fork: EthereumHardfork) -> Self { - match fork { - EthereumHardfork::Frontier => Self::FRONTIER, - EthereumHardfork::Homestead => Self::HOMESTEAD, - EthereumHardfork::Dao => Self::HOMESTEAD, - EthereumHardfork::Tangerine => Self::TANGERINE, - EthereumHardfork::SpuriousDragon => Self::SPURIOUS_DRAGON, - EthereumHardfork::Byzantium => Self::BYZANTIUM, - EthereumHardfork::Constantinople => Self::CONSTANTINOPLE, - EthereumHardfork::Petersburg => Self::PETERSBURG, - EthereumHardfork::Istanbul => Self::ISTANBUL, - EthereumHardfork::Muirglacier => Self::MUIR_GLACIER, - EthereumHardfork::Berlin => Self::BERLIN, - EthereumHardfork::London => Self::LONDON, - EthereumHardfork::ArrowGlacier => Self::LONDON, - EthereumHardfork::GrayGlacier => Self::GRAY_GLACIER, - EthereumHardfork::Paris => Self::MERGE, - EthereumHardfork::Shanghai => Self::SHANGHAI, - EthereumHardfork::Cancun | EthereumHardfork::Latest => Self::CANCUN, - EthereumHardfork::Prague => Self::PRAGUE, - } +/// Map an OptimismHardfork enum into its corresponding OpSpecId. +pub fn spec_id_from_optimism_hardfork(hardfork: OpHardfork) -> OpSpecId { + match hardfork { + OpHardfork::Bedrock => OpSpecId::BEDROCK, + OpHardfork::Regolith => OpSpecId::REGOLITH, + OpHardfork::Canyon => OpSpecId::CANYON, + OpHardfork::Ecotone => OpSpecId::ECOTONE, + OpHardfork::Fjord => OpSpecId::FJORD, + OpHardfork::Granite => OpSpecId::GRANITE, + OpHardfork::Holocene => OpSpecId::HOLOCENE, + OpHardfork::Isthmus => OpSpecId::ISTHMUS, + OpHardfork::Interop => OpSpecId::INTEROP, } } -impl> From for EthereumHardfork { - fn from(block: T) -> Self { - let num = match block.into() { - BlockNumberOrTag::Earliest => 0, - BlockNumberOrTag::Number(num) => num, - _ => u64::MAX, - }; - - match num { - _i if num < 1_150_000 => Self::Frontier, - _i if num < 1_920_000 => Self::Dao, - _i if num < 2_463_000 => Self::Homestead, - _i if num < 2_675_000 => Self::Tangerine, - _i if num < 4_370_000 => Self::SpuriousDragon, - _i if num < 7_280_000 => Self::Byzantium, - _i if num < 9_069_000 => Self::Constantinople, - _i if num < 9_200_000 => Self::Istanbul, - _i if num < 12_244_000 => Self::Muirglacier, - _i if num < 12_965_000 => Self::Berlin, - _i if num < 13_773_000 => Self::London, - _i if num < 15_050_000 => Self::ArrowGlacier, - _i if num < 17_034_870 => Self::Paris, - _i if num < 19_426_587 => Self::Shanghai, - _ => Self::Latest, - } - } -} +/// Convert a `BlockNumberOrTag` into an `EthereumHardfork`. +pub fn ethereum_hardfork_from_block_tag(block: impl Into) -> EthereumHardfork { + let num = match block.into() { + BlockNumberOrTag::Earliest => 0, + BlockNumberOrTag::Number(num) => num, + _ => u64::MAX, + }; -#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub enum OptimismHardfork { - Bedrock, - Regolith, - Canyon, - Ecotone, - Fjord, - Granite, - Holocene, - #[default] - Isthmus, + EthereumHardfork::from_mainnet_block_number(num) } -impl OptimismHardfork { - pub fn into_eth_spec(self) -> SpecId { - let op_spec: OpSpecId = self.into(); - op_spec.into_eth_spec() - } -} +#[cfg(test)] +mod tests { + use super::*; + use alloy_hardforks::ethereum::mainnet::*; + #[allow(unused_imports)] + use alloy_rpc_types::BlockNumberOrTag; -impl FromStr for OptimismHardfork { - type Err = eyre::Report; + #[test] + fn test_ethereum_spec_id_mapping() { + assert_eq!(spec_id_from_ethereum_hardfork(EthereumHardfork::Frontier), SpecId::FRONTIER); + assert_eq!(spec_id_from_ethereum_hardfork(EthereumHardfork::Homestead), SpecId::HOMESTEAD); - fn from_str(s: &str) -> Result { - let s = s.to_lowercase(); - let hardfork = match s.as_str() { - "bedrock" => Self::Bedrock, - "regolith" => Self::Regolith, - "canyon" => Self::Canyon, - "ecotone" => Self::Ecotone, - "fjord" => Self::Fjord, - "granite" => Self::Granite, - "holocene" => Self::Holocene, - "isthmus" => Self::Isthmus, - _ => bail!("Unknown hardfork {s}"), - }; - Ok(hardfork) + // Test latest hardforks + assert_eq!(spec_id_from_ethereum_hardfork(EthereumHardfork::Cancun), SpecId::CANCUN); + assert_eq!(spec_id_from_ethereum_hardfork(EthereumHardfork::Prague), SpecId::PRAGUE); } -} - -impl From for OpSpecId { - fn from(fork: OptimismHardfork) -> Self { - match fork { - OptimismHardfork::Bedrock => Self::BEDROCK, - OptimismHardfork::Regolith => Self::REGOLITH, - OptimismHardfork::Canyon => Self::CANYON, - OptimismHardfork::Ecotone => Self::ECOTONE, - OptimismHardfork::Fjord => Self::FJORD, - OptimismHardfork::Granite => Self::GRANITE, - OptimismHardfork::Holocene => Self::HOLOCENE, - OptimismHardfork::Isthmus => Self::ISTHMUS, - } - } -} - -#[cfg(test)] -mod tests { - use crate::EthereumHardfork; #[test] - fn test_hardfork_blocks() { - let hf: EthereumHardfork = 12_965_000u64.into(); - assert_eq!(hf, EthereumHardfork::London); + fn test_optimism_spec_id_mapping() { + assert_eq!(spec_id_from_optimism_hardfork(OpHardfork::Bedrock), OpSpecId::BEDROCK); + assert_eq!(spec_id_from_optimism_hardfork(OpHardfork::Regolith), OpSpecId::REGOLITH); - let hf: EthereumHardfork = 4370000u64.into(); - assert_eq!(hf, EthereumHardfork::Byzantium); + // Test latest hardforks + assert_eq!(spec_id_from_optimism_hardfork(OpHardfork::Holocene), OpSpecId::HOLOCENE); + assert_eq!(spec_id_from_optimism_hardfork(OpHardfork::Interop), OpSpecId::INTEROP); + } - let hf: EthereumHardfork = 12244000u64.into(); - assert_eq!(hf, EthereumHardfork::Berlin); + #[test] + fn test_hardfork_from_block_tag_numbers() { + assert_eq!( + ethereum_hardfork_from_block_tag(MAINNET_HOMESTEAD_BLOCK - 1), + EthereumHardfork::Frontier + ); + assert_eq!( + ethereum_hardfork_from_block_tag(MAINNET_LONDON_BLOCK + 1), + EthereumHardfork::London + ); } } diff --git a/crates/anvil/src/lib.rs b/crates/anvil/src/lib.rs index 77e072e0aa1f2..5ee4fead559b2 100644 --- a/crates/anvil/src/lib.rs +++ b/crates/anvil/src/lib.rs @@ -47,8 +47,7 @@ pub use config::{ }; mod hardfork; -pub use hardfork::{EthereumHardfork, OptimismHardfork}; - +pub use alloy_hardforks::EthereumHardfork; /// ethereum related implementations pub mod eth; /// Evm related abstractions diff --git a/crates/anvil/tests/it/anvil.rs b/crates/anvil/tests/it/anvil.rs index 329caea844b45..721aa404b36e1 100644 --- a/crates/anvil/tests/it/anvil.rs +++ b/crates/anvil/tests/it/anvil.rs @@ -2,9 +2,10 @@ use alloy_consensus::EMPTY_ROOT_HASH; use alloy_eips::BlockNumberOrTag; +use alloy_hardforks::EthereumHardfork; use alloy_primitives::Address; use alloy_provider::Provider; -use anvil::{spawn, EthereumHardfork, NodeConfig}; +use anvil::{spawn, NodeConfig}; #[tokio::test(flavor = "multi_thread")] async fn test_can_change_mining_mode() { diff --git a/crates/anvil/tests/it/anvil_api.rs b/crates/anvil/tests/it/anvil_api.rs index ce337714587b9..d4af986814ed6 100644 --- a/crates/anvil/tests/it/anvil_api.rs +++ b/crates/anvil/tests/it/anvil_api.rs @@ -6,6 +6,7 @@ use crate::{ utils::http_provider_with_signer, }; use alloy_consensus::{SignableTransaction, TxEip1559}; +use alloy_hardforks::EthereumHardfork; use alloy_network::{EthereumWallet, TransactionBuilder, TxSignerSync}; use alloy_primitives::{address, fixed_bytes, utils::Unit, Address, Bytes, TxKind, U256}; use alloy_provider::{ext::TxPoolApi, Provider}; @@ -21,7 +22,7 @@ use anvil::{ api::CLIENT_VERSION, backend::mem::{EXECUTOR, P256_DELEGATION_CONTRACT, P256_DELEGATION_RUNTIME_CODE}, }, - spawn, EthereumHardfork, NodeConfig, + spawn, NodeConfig, }; use anvil_core::{ eth::{ diff --git a/crates/anvil/tests/it/eip4844.rs b/crates/anvil/tests/it/eip4844.rs index 633c8a01bdef0..2d713c3d955e3 100644 --- a/crates/anvil/tests/it/eip4844.rs +++ b/crates/anvil/tests/it/eip4844.rs @@ -4,12 +4,13 @@ use alloy_eips::{ eip4844::{BLOB_TX_MIN_BLOB_GASPRICE, DATA_GAS_PER_BLOB, MAX_DATA_GAS_PER_BLOCK_DENCUN}, Typed2718, }; +use alloy_hardforks::EthereumHardfork; use alloy_network::{EthereumWallet, ReceiptResponse, TransactionBuilder, TransactionBuilder4844}; use alloy_primitives::{b256, Address, U256}; use alloy_provider::Provider; use alloy_rpc_types::{BlockId, TransactionRequest}; use alloy_serde::WithOtherFields; -use anvil::{spawn, EthereumHardfork, NodeConfig}; +use anvil::{spawn, NodeConfig}; #[tokio::test(flavor = "multi_thread")] async fn can_send_eip4844_transaction() { diff --git a/crates/anvil/tests/it/eip7702.rs b/crates/anvil/tests/it/eip7702.rs index c09412c85e306..9424360119e4e 100644 --- a/crates/anvil/tests/it/eip7702.rs +++ b/crates/anvil/tests/it/eip7702.rs @@ -1,12 +1,13 @@ use crate::utils::http_provider; use alloy_consensus::{transaction::TxEip7702, SignableTransaction}; +use alloy_hardforks::EthereumHardfork; use alloy_network::{ReceiptResponse, TransactionBuilder, TxSignerSync}; use alloy_primitives::{bytes, U256}; use alloy_provider::{PendingTransactionConfig, Provider}; use alloy_rpc_types::{Authorization, TransactionRequest}; use alloy_serde::WithOtherFields; use alloy_signer::SignerSync; -use anvil::{spawn, EthereumHardfork, NodeConfig}; +use anvil::{spawn, NodeConfig}; #[tokio::test(flavor = "multi_thread")] async fn can_send_eip7702_tx() { diff --git a/crates/anvil/tests/it/otterscan.rs b/crates/anvil/tests/it/otterscan.rs index 3809e3183e1a7..ffd70d1349ddb 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_hardforks::EthereumHardfork; use alloy_network::TransactionResponse; use alloy_primitives::{address, Address, Bytes, U256}; use alloy_provider::Provider; @@ -10,7 +11,7 @@ use alloy_rpc_types::{ }; use alloy_serde::WithOtherFields; use alloy_sol_types::{sol, SolCall, SolError, SolValue}; -use anvil::{spawn, EthereumHardfork, NodeConfig}; +use anvil::{spawn, NodeConfig}; use std::collections::VecDeque; #[tokio::test(flavor = "multi_thread")] diff --git a/crates/anvil/tests/it/traces.rs b/crates/anvil/tests/it/traces.rs index 849956cabe5dd..2e073ca9c8735 100644 --- a/crates/anvil/tests/it/traces.rs +++ b/crates/anvil/tests/it/traces.rs @@ -4,6 +4,7 @@ use crate::{ utils::http_provider_with_signer, }; use alloy_eips::BlockId; +use alloy_hardforks::EthereumHardfork; use alloy_network::{EthereumWallet, TransactionBuilder}; use alloy_primitives::{ hex::{self, FromHex}, @@ -27,7 +28,7 @@ use alloy_rpc_types::{ }; use alloy_serde::WithOtherFields; use alloy_sol_types::sol; -use anvil::{spawn, EthereumHardfork, NodeConfig}; +use anvil::{spawn, NodeConfig}; #[tokio::test(flavor = "multi_thread")] async fn test_get_transfer_parity_traces() { diff --git a/crates/anvil/tests/it/transaction.rs b/crates/anvil/tests/it/transaction.rs index 953c30515d3ef..7cb681af85a14 100644 --- a/crates/anvil/tests/it/transaction.rs +++ b/crates/anvil/tests/it/transaction.rs @@ -2,6 +2,7 @@ use crate::{ abi::{Greeter, Multicall, SimpleStorage}, utils::{connect_pubsub, http_provider_with_signer}, }; +use alloy_hardforks::EthereumHardfork; use alloy_network::{EthereumWallet, TransactionBuilder, TransactionResponse}; use alloy_primitives::{address, hex, map::B256HashSet, Address, Bytes, FixedBytes, U256}; use alloy_provider::{Provider, WsConnect}; @@ -12,7 +13,7 @@ use alloy_rpc_types::{ }; use alloy_serde::WithOtherFields; use alloy_sol_types::SolValue; -use anvil::{spawn, EthereumHardfork, NodeConfig}; +use anvil::{spawn, NodeConfig}; use eyre::Ok; use futures::{future::join_all, FutureExt, StreamExt}; use std::{str::FromStr, time::Duration}; diff --git a/crates/cast/Cargo.toml b/crates/cast/Cargo.toml index 26f001132baff..2dda3ba341872 100644 --- a/crates/cast/Cargo.toml +++ b/crates/cast/Cargo.toml @@ -53,6 +53,7 @@ alloy-signer.workspace = true alloy-sol-types.workspace = true alloy-transport.workspace = true alloy-ens = { workspace = true, features = ["provider"] } +alloy-hardforks.workspace = true op-alloy-flz.workspace = true op-alloy-consensus = { workspace = true, features = ["alloy-compat"] } diff --git a/crates/cast/tests/cli/main.rs b/crates/cast/tests/cli/main.rs index 1a0c0bf958cf8..eca950b2f89d4 100644 --- a/crates/cast/tests/cli/main.rs +++ b/crates/cast/tests/cli/main.rs @@ -1,11 +1,12 @@ //! Contains various tests for checking cast commands use alloy_chains::NamedChain; +use alloy_hardforks::EthereumHardfork; use alloy_network::{TransactionBuilder, TransactionResponse}; use alloy_primitives::{address, b256, Bytes, B256}; use alloy_provider::{Provider, ProviderBuilder}; use alloy_rpc_types::{BlockNumberOrTag, Index, TransactionRequest}; -use anvil::{EthereumHardfork, NodeConfig}; +use anvil::NodeConfig; use foundry_test_utils::{ rpc::{ next_etherscan_api_key, next_http_archive_rpc_url, next_http_rpc_endpoint, diff --git a/crates/forge/Cargo.toml b/crates/forge/Cargo.toml index c3251ed76c9eb..d823ca3285140 100644 --- a/crates/forge/Cargo.toml +++ b/crates/forge/Cargo.toml @@ -63,6 +63,7 @@ alloy-rpc-types.workspace = true alloy-serde.workspace = true alloy-signer.workspace = true alloy-transport.workspace = true +alloy-hardforks.workspace = true revm.workspace = true diff --git a/crates/forge/tests/cli/script.rs b/crates/forge/tests/cli/script.rs index d72c21fce60ff..1d6f415aef1d4 100644 --- a/crates/forge/tests/cli/script.rs +++ b/crates/forge/tests/cli/script.rs @@ -1,8 +1,9 @@ //! Contains various tests related to `forge script`. use crate::constants::TEMPLATE_CONTRACT; +use alloy_hardforks::EthereumHardfork; use alloy_primitives::{address, hex, Address, Bytes}; -use anvil::{spawn, EthereumHardfork, NodeConfig}; +use anvil::{spawn, NodeConfig}; use forge_script_sequence::ScriptSequence; use foundry_test_utils::{ rpc::{self, next_http_archive_rpc_url}, From 07dee8164299a22f4826242b35e81387b4a55005 Mon Sep 17 00:00:00 2001 From: Yash Atreya <44857776+yash-atreya@users.noreply.github.com> Date: Wed, 28 May 2025 13:03:08 +0100 Subject: [PATCH 049/232] fix(`anvil`): latest evm version should be prague (#10653) * fix(`anvil`): latest evm version should be prague * fix test * nit --- crates/anvil/src/cmd.rs | 2 +- crates/anvil/src/config.rs | 6 +++--- crates/anvil/tests/it/anvil_api.rs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/anvil/src/cmd.rs b/crates/anvil/src/cmd.rs index c8223a76ed959..4ca9624d57f6e 100644 --- a/crates/anvil/src/cmd.rs +++ b/crates/anvil/src/cmd.rs @@ -79,7 +79,7 @@ pub struct NodeArgs { /// The EVM hardfork to use. /// - /// Choose the hardfork by name, e.g. `cancun`, `shanghai`, `paris`, `london`, etc... + /// Choose the hardfork by name, e.g. `prague`, `cancun`, `shanghai`, `paris`, `london`, etc... /// [default: latest] #[arg(long)] pub hardfork: Option, diff --git a/crates/anvil/src/config.rs b/crates/anvil/src/config.rs index 1cde743c3e952..d86515f9f8fba 100644 --- a/crates/anvil/src/config.rs +++ b/crates/anvil/src/config.rs @@ -525,15 +525,15 @@ impl NodeConfig { /// Returns the hardfork to use pub fn get_hardfork(&self) -> ChainHardfork { if self.odyssey { - return ChainHardfork::Ethereum(EthereumHardfork::Prague); + return ChainHardfork::Ethereum(EthereumHardfork::default()); } if let Some(hardfork) = self.hardfork { return hardfork; } if self.enable_optimism { - return OpHardfork::Isthmus.into(); + return OpHardfork::default().into(); } - EthereumHardfork::Cancun.into() + EthereumHardfork::default().into() } /// Sets a custom code size limit diff --git a/crates/anvil/tests/it/anvil_api.rs b/crates/anvil/tests/it/anvil_api.rs index d4af986814ed6..5b4bcd78d2059 100644 --- a/crates/anvil/tests/it/anvil_api.rs +++ b/crates/anvil/tests/it/anvil_api.rs @@ -449,7 +449,7 @@ async fn can_get_node_info() { let block_number = provider.get_block_number().await.unwrap(); let block = provider.get_block(BlockId::from(block_number)).await.unwrap().unwrap(); - let hard_fork: &str = SpecId::CANCUN.into(); + let hard_fork: &str = SpecId::PRAGUE.into(); let expected_node_info = NodeInfo { current_block_number: 0_u64, From 17b50b4242c36fa902d2c31f8d1b53b17bed0b31 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Sep 2025 02:00:01 +0700 Subject: [PATCH 050/232] chore(deps): bump tracing-subscriber (#51) Bumps the cargo group with 1 update in the / directory: [tracing-subscriber](https://github.com/tokio-rs/tracing). Updates `tracing-subscriber` from 0.3.19 to 0.3.20 - [Release notes](https://github.com/tokio-rs/tracing/releases) - [Commits](https://github.com/tokio-rs/tracing/compare/tracing-subscriber-0.3.19...tracing-subscriber-0.3.20) --- updated-dependencies: - dependency-name: tracing-subscriber dependency-version: 0.3.20 dependency-type: direct:production dependency-group: cargo ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 76 +++++++++++++++++++----------------------------------- 1 file changed, 27 insertions(+), 49 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1fa7e6a150282..c6cae03ce7321 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1074,7 +1074,7 @@ dependencies = [ "thiserror 2.0.12", "tokio", "tracing", - "tracing-subscriber 0.3.19", + "tracing-subscriber 0.3.20", "yansi", ] @@ -2225,7 +2225,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "234113d19d0d7d613b40e86fb654acf958910802bcceab913a4f9e7cda03b1a4" dependencies = [ "memchr", - "regex-automata 0.4.9", + "regex-automata", "serde", ] @@ -2475,7 +2475,7 @@ dependencies = [ "time", "tokio", "tracing", - "tracing-subscriber 0.3.19", + "tracing-subscriber 0.3.20", "walkdir", "yansi", ] @@ -3896,7 +3896,7 @@ dependencies = [ "thiserror 2.0.12", "toml 0.8.22", "tracing", - "tracing-subscriber 0.3.19", + "tracing-subscriber 0.3.20", ] [[package]] @@ -4153,7 +4153,7 @@ dependencies = [ "tikv-jemallocator", "tokio", "tracing", - "tracing-subscriber 0.3.19", + "tracing-subscriber 0.3.20", "tracing-tracy", "tracy-client", "yansi", @@ -4619,7 +4619,7 @@ dependencies = [ "tempfile", "tokio", "tracing", - "tracing-subscriber 0.3.19", + "tracing-subscriber 0.3.20", "ui_test", "zip-extract", ] @@ -4898,8 +4898,8 @@ dependencies = [ "aho-corasick", "bstr", "log", - "regex-automata 0.4.9", - "regex-syntax 0.8.5", + "regex-automata", + "regex-syntax", ] [[package]] @@ -5290,7 +5290,7 @@ dependencies = [ "globset", "log", "memchr", - "regex-automata 0.4.9", + "regex-automata", "same-file", "walkdir", "winapi-util", @@ -5668,7 +5668,7 @@ dependencies = [ "lalrpop-util", "petgraph", "regex", - "regex-syntax 0.8.5", + "regex-syntax", "sha3", "string_cache", "term", @@ -5682,7 +5682,7 @@ version = "0.22.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5baa5e9ff84f1aefd264e6869907646538a52147a755d494517a8007fb48733" dependencies = [ - "regex-automata 0.4.9", + "regex-automata", "rustversion", ] @@ -5866,7 +5866,7 @@ dependencies = [ "generator", "scoped-tls", "tracing", - "tracing-subscriber 0.3.19", + "tracing-subscriber 0.3.20", ] [[package]] @@ -5967,11 +5967,11 @@ dependencies = [ [[package]] name = "matchers" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" dependencies = [ - "regex-automata 0.1.10", + "regex-automata", ] [[package]] @@ -6254,12 +6254,11 @@ checksum = "5e0826a989adedc2a244799e823aece04662b66609d96af8dff7ac6df9a8925d" [[package]] name = "nu-ansi-term" -version = "0.46.0" +version = "0.50.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399" dependencies = [ - "overload", - "winapi", + "windows-sys 0.52.0", ] [[package]] @@ -6561,12 +6560,6 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a80800c0488c3a21695ea981a54918fbb37abf04f4d0720c453632255e2ff0e" -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - [[package]] name = "owo-colors" version = "3.5.0" @@ -7105,7 +7098,7 @@ dependencies = [ "rand 0.8.5", "rand_chacha 0.3.1", "rand_xorshift", - "regex-syntax 0.8.5", + "regex-syntax", "rusty-fork", "tempfile", "unarray", @@ -7463,17 +7456,8 @@ checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.9", - "regex-syntax 0.8.5", -] - -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" -dependencies = [ - "regex-syntax 0.6.29", + "regex-automata", + "regex-syntax", ] [[package]] @@ -7484,7 +7468,7 @@ checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.5", + "regex-syntax", ] [[package]] @@ -7493,12 +7477,6 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a" -[[package]] -name = "regex-syntax" -version = "0.6.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" - [[package]] name = "regex-syntax" version = "0.8.5" @@ -9598,7 +9576,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b1581020d7a273442f5b45074a6a57d5757ad0a47dac0e9f0bd57b81936f3db" dependencies = [ "tracing", - "tracing-subscriber 0.3.19", + "tracing-subscriber 0.3.20", ] [[package]] @@ -9635,14 +9613,14 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.19" +version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" +checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" dependencies = [ "matchers", "nu-ansi-term", "once_cell", - "regex", + "regex-automata", "sharded-slab", "smallvec", "thread_local", @@ -9658,7 +9636,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eaa1852afa96e0fe9e44caa53dc0bd2d9d05e0f2611ce09f97f8677af56e4ba" dependencies = [ "tracing-core", - "tracing-subscriber 0.3.19", + "tracing-subscriber 0.3.20", "tracy-client", ] From fcfa587cbfce70b8eb32ac87207cd8a2e2c4f726 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Sun, 7 Sep 2025 23:17:57 +0700 Subject: [PATCH 051/232] Update test.yml (#52) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .github/workflows/test.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f4d5d2d361f5a..716abb3648f13 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -4,8 +4,10 @@ on: push: branches: - master + - main + - dev + pull_request: - concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} cancel-in-progress: true From 5973becffce4febb02046b125adb408c5c4d5f3c Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Mon, 8 Sep 2025 23:12:20 +0700 Subject: [PATCH 052/232] Update docker-image.yml (#53) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .github/workflows/docker-image.yml | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index e0c9c518e8748..9c2e6a62fd947 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -1,21 +1,15 @@ name: Docker Image CI - on: push: branches: [ "master" ] pull_request: branches: [ "master" ] - permissions: - contents: read - + contents: read jobs: - build: - runs-on: ubuntu-latest - steps: - uses: actions/checkout@v4 - name: Build the Docker image - run: docker build . --file Dockerfile --tag my-image-name:${{ github.sha }} + run: docker build . --file Dockerfile --tag my-image-name:${{ github.sha }} From 70c73b4b5afaafeb5c587e690df25f6f93f2e94c Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Sat, 13 Sep 2025 04:33:10 +0700 Subject: [PATCH 053/232] Create ci.yml (#57) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .circleci/ci.yml | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 .circleci/ci.yml diff --git a/.circleci/ci.yml b/.circleci/ci.yml new file mode 100644 index 0000000000000..d5d401c51893c --- /dev/null +++ b/.circleci/ci.yml @@ -0,0 +1,31 @@ +# Use the latest 2.1 version of CircleCI pipeline process engine. +# See: https://circleci.com/docs/configuration-reference +version: 2.1 + +# Define a job to be invoked later in a workflow. +# See: https://circleci.com/docs/jobs-steps/#jobs-overview & https://circleci.com/docs/configuration-reference/#jobs +jobs: + say-hello: + # Specify the execution environment. You can specify an image from Docker Hub or use one of our convenience images from CircleCI's Developer Hub. + # See: https://circleci.com/docs/executor-intro/ & https://circleci.com/docs/configuration-reference/#executor-job + docker: + # Specify the version you desire here + # See: https://circleci.com/developer/images/image/cimg/base + - image: cimg/base:current + + # Add steps to the job + # See: https://circleci.com/docs/jobs-steps/#steps-overview & https://circleci.com/docs/configuration-reference/#steps + steps: + # Checkout the code as the first step. + - checkout + - run: + name: "Say hello" + command: "echo Hello, World!" + +# Orchestrate jobs using workflows +# See: https://circleci.com/docs/workflows/ & https://circleci.com/docs/configuration-reference/#workflows +workflows: + say-hello-workflow: # This is the name of the workflow, feel free to change it to better match your workflow. + # Inside the workflow, you define the jobs you want to run. + jobs: + - say-hello From 913e6393fab483e6ddd9906fe97faab4939577fb Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Sat, 13 Sep 2025 16:55:29 +0700 Subject: [PATCH 054/232] Create ci_cargo.yml (#59) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .circleci/ci_cargo.yml | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 .circleci/ci_cargo.yml diff --git a/.circleci/ci_cargo.yml b/.circleci/ci_cargo.yml new file mode 100644 index 0000000000000..46a18d45a5fca --- /dev/null +++ b/.circleci/ci_cargo.yml @@ -0,0 +1,37 @@ +version: 2.1 + +jobs: + build-and-test: + docker: + - image: cimg/rust:1.88.0 + steps: + - checkout + - restore_cache: + keys: + - v1-cargo-{{ checksum "Cargo.lock" }} + - v1-cargo- + - run: + name: "Check formatting" + command: cargo fmt -- --check + - run: + name: "Run tests" + command: cargo test + - save_cache: + key: v1-cargo-{{ checksum "Cargo.lock" }} + paths: + - "~/.cargo/bin" + - "~/.cargo/registry/index" + - "~/.cargo/registry/cache" + - "~/.cargo/git/db" + - "target" + - run: + name: "Check formatting" + command: cargo fmt -- --check + - run: + name: "Run tests" + command: cargo test + +workflows: + ci: + jobs: + - build-and-test From 8575916b7675f246b54daf70cfddccb3f5b97fb0 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Sat, 13 Sep 2025 18:39:46 +0700 Subject: [PATCH 055/232] Create web3_defi_gamefi.yml (#61) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .circleci/web3_defi_gamefi.yml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 .circleci/web3_defi_gamefi.yml diff --git a/.circleci/web3_defi_gamefi.yml b/.circleci/web3_defi_gamefi.yml new file mode 100644 index 0000000000000..edb6605e3f101 --- /dev/null +++ b/.circleci/web3_defi_gamefi.yml @@ -0,0 +1,26 @@ +# Use the latest 2.1 version of CircleCI pipeline process engine. +# See: https://circleci.com/docs/configuration-reference + +version: 2.1 +executors: + my-custom-executor: + docker: + - image: cimg/base:stable + auth: + # ensure you have first added these secrets + # visit app.circleci.com/settings/project/github/Dargon789/foundry/environment-variables + username: $DOCKER_HUB_USER + password: $DOCKER_HUB_PASSWORD +jobs: + web3-defi-game-project-: + + executor: my-custom-executor + steps: + - checkout + - run: | + # echo Hello, World! + +workflows: + my-custom-workflow: + jobs: + - web3-defi-game-project- From a07134ed485f776c739b0809a93a8c3c81add390 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Sat, 13 Sep 2025 23:51:21 +0700 Subject: [PATCH 056/232] Update ci.yml (#66) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .circleci/ci.yml | 37 ++++++++++--------------------------- 1 file changed, 10 insertions(+), 27 deletions(-) diff --git a/.circleci/ci.yml b/.circleci/ci.yml index d5d401c51893c..b908ef7ada8fb 100644 --- a/.circleci/ci.yml +++ b/.circleci/ci.yml @@ -1,31 +1,14 @@ -# Use the latest 2.1 version of CircleCI pipeline process engine. -# See: https://circleci.com/docs/configuration-reference -version: 2.1 - -# Define a job to be invoked later in a workflow. -# See: https://circleci.com/docs/jobs-steps/#jobs-overview & https://circleci.com/docs/configuration-reference/#jobs -jobs: - say-hello: - # Specify the execution environment. You can specify an image from Docker Hub or use one of our convenience images from CircleCI's Developer Hub. - # See: https://circleci.com/docs/executor-intro/ & https://circleci.com/docs/configuration-reference/#executor-job + build_and_test: docker: - # Specify the version you desire here - # See: https://circleci.com/developer/images/image/cimg/base - - image: cimg/base:current - - # Add steps to the job - # See: https://circleci.com/docs/jobs-steps/#steps-overview & https://circleci.com/docs/configuration-reference/#steps + - image: cimg/rust:1.75.0 steps: - # Checkout the code as the first step. - checkout - run: - name: "Say hello" - command: "echo Hello, World!" - -# Orchestrate jobs using workflows -# See: https://circleci.com/docs/workflows/ & https://circleci.com/docs/configuration-reference/#workflows -workflows: - say-hello-workflow: # This is the name of the workflow, feel free to change it to better match your workflow. - # Inside the workflow, you define the jobs you want to run. - jobs: - - say-hello + name: "Check formatting" + command: "cargo fmt --all -- --check" + - run: + name: "Run Clippy" + command: "cargo clippy --all-targets -- -D warnings" + - run: + name: "Run tests" + command: "cargo test --all-features" From bb76ae4cbcc85360612363a7934d07c1422331a8 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Tue, 16 Sep 2025 03:39:32 +0700 Subject: [PATCH 057/232] Create config.yml (#71) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .circleci/config.yml | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 .circleci/config.yml diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000000000..76b2889f1c4b2 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,32 @@ +# Use the latest 2.1 version of CircleCI pipeline process engine. +# See: https://circleci.com/docs/configuration-reference +version: 2.1 + +# Define a job to be invoked later in a workflow. +# See: https://circleci.com/docs/jobs-steps/#jobs-overview & https://circleci.com/docs/configuration-reference/#jobs +jobs: + say-hello: + # Specify the execution environment. You can specify an image from Docker Hub or use one of our convenience images from CircleCI's Developer Hub. + # See: https://circleci.com/docs/executor-intro/ & https://circleci.com/docs/configuration-reference/#executor-job + docker: + # Specify the version you desire here + # See: https://circleci.com/developer/images/image/cimg/base + - image: cimg/base:current + + # Add steps to the job + # See: https://circleci.com/docs/jobs-steps/#steps-overview & https://circleci.com/docs/configuration-reference/#steps + steps: + # Checkout the code as the first step. + - checkout + - run: + name: "Say hello" + command: "echo Hello, World!" + +# Orchestrate jobs using workflows +# See: https://circleci.com/docs/workflows/ & https://circleci.com/docs/configuration-reference/#workflows +workflows: + say-hello-workflow: # This is the name of the workflow, feel free to change it to better match your workflow. + # Inside the workflow, you define the jobs you want to run. + jobs: + - say-hello + From 9c4a6353ac372fd499792e48fbfc01ec247f1a11 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Mon, 22 Sep 2025 01:41:52 +0700 Subject: [PATCH 058/232] Update dependencies.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .github/workflows/dependencies.yml | 50 +++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 8 deletions(-) diff --git a/.github/workflows/dependencies.yml b/.github/workflows/dependencies.yml index e452a68c80967..53e2ca70b23b0 100644 --- a/.github/workflows/dependencies.yml +++ b/.github/workflows/dependencies.yml @@ -7,14 +7,48 @@ on: # Run weekly - cron: "0 0 * * SUN" workflow_dispatch: -# Needed so we can run it manually - -permissions: - contents: write - pull-requests: write + # Needed so we can run it manually +env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + BRANCH: cargo-update + TITLE: "chore(deps): weekly `cargo update`" + BODY: | + Automation to keep dependencies in `Cargo.lock` current. +
cargo update log +

+ ```log + $cargo_update_log + ``` +

+
jobs: update: - uses: ithacaxyz/ci/.github/workflows/cargo-update-pr.yml@main - secrets: - token: ${{ secrets.GITHUB_TOKEN }} + name: Update + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@nightly + + - name: cargo update + # Remove first line that always just says "Updating crates.io index" + run: cargo update --color never 2>&1 | sed '/crates.io index/d' | tee -a cargo_update.log + + - name: craft commit message and PR body + id: msg + run: | + export cargo_update_log="$(cat cargo_update.log)" + echo "commit_message<> $GITHUB_OUTPUT + printf "$TITLE\n\n$cargo_update_log\n" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + echo "body<> $GITHUB_OUTPUT + echo "$BODY" | envsubst >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + - name: Create Pull Request + uses: peter-evans/create-pull-request@v6 + with: + add-paths: ./Cargo.lock + commit-message: ${{ steps.msg.outputs.commit_message }} + title: ${{ env.TITLE }} + body: ${{ steps.msg.outputs.body }} + branch: ${{ env.BRANCH }} From a2eb55138f3a3eb17f33e363c608d99f67a6bffd Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Mon, 22 Sep 2025 01:43:43 +0700 Subject: [PATCH 059/232] Potential fix for code scanning alert no. 21: Workflow does not contain permissions Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .github/workflows/dependencies.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/dependencies.yml b/.github/workflows/dependencies.yml index 53e2ca70b23b0..184e5d13f2c73 100644 --- a/.github/workflows/dependencies.yml +++ b/.github/workflows/dependencies.yml @@ -26,6 +26,9 @@ jobs: update: name: Update runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@nightly From 58a14551db4bf60eaf2dfca242e6e9a062e5e3e8 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Tue, 16 Sep 2025 05:14:25 +0700 Subject: [PATCH 060/232] Create ci_cargo.yml (#72) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .circleci/ci_cargo.yml | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 .circleci/ci_cargo.yml diff --git a/.circleci/ci_cargo.yml b/.circleci/ci_cargo.yml new file mode 100644 index 0000000000000..46a18d45a5fca --- /dev/null +++ b/.circleci/ci_cargo.yml @@ -0,0 +1,37 @@ +version: 2.1 + +jobs: + build-and-test: + docker: + - image: cimg/rust:1.88.0 + steps: + - checkout + - restore_cache: + keys: + - v1-cargo-{{ checksum "Cargo.lock" }} + - v1-cargo- + - run: + name: "Check formatting" + command: cargo fmt -- --check + - run: + name: "Run tests" + command: cargo test + - save_cache: + key: v1-cargo-{{ checksum "Cargo.lock" }} + paths: + - "~/.cargo/bin" + - "~/.cargo/registry/index" + - "~/.cargo/registry/cache" + - "~/.cargo/git/db" + - "target" + - run: + name: "Check formatting" + command: cargo fmt -- --check + - run: + name: "Run tests" + command: cargo test + +workflows: + ci: + jobs: + - build-and-test From 82923a7714a069007d6cc2770e5fa908276e258c Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Fri, 10 Oct 2025 11:46:59 +0700 Subject: [PATCH 061/232] Create config.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .circleci/config.yml | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 .circleci/config.yml diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000000000..f967cfaa30db5 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,31 @@ +# Use the latest 2.1 version of CircleCI pipeline process engine. +# See: https://circleci.com/docs/reference/configuration-reference +version: 2.1 + +# Define a job to be invoked later in a workflow. +# See: https://circleci.com/docs/guides/orchestrate/jobs-steps/#jobs-overview & https://circleci.com/docs/reference/configuration-reference/#jobs +jobs: + say-hello: + # Specify the execution environment. You can specify an image from Docker Hub or use one of our convenience images from CircleCI's Developer Hub. + # See: https://circleci.com/docs/guides/execution-managed/executor-intro/ & https://circleci.com/docs/reference/configuration-reference/#executor-job + docker: + # Specify the version you desire here + # See: https://circleci.com/developer/images/image/cimg/base + - image: cimg/base:current + + # Add steps to the job + # See: https://circleci.com/docs/guides/orchestrate/jobs-steps/#steps-overview & https://circleci.com/docs/reference/configuration-reference/#steps + steps: + # Checkout the code as the first step. + - checkout + - run: + name: "Say hello" + command: "echo Hello, World!" + +# Orchestrate jobs using workflows +# See: https://circleci.com/docs/guides/orchestrate/workflows/ & https://circleci.com/docs/reference/configuration-reference/#workflows +workflows: + say-hello-workflow: # This is the name of the workflow, feel free to change it to better match your workflow. + # Inside the workflow, you define the jobs you want to run. + jobs: + - say-hello From f0b1a99ac7c7d91ee2e6421f63a8666b2ab42ec5 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Mon, 13 Oct 2025 08:00:39 +0700 Subject: [PATCH 062/232] Potential fix for code scanning alert no. 2: Workflow does not contain permissions Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .github/workflows/apisec-scan.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/apisec-scan.yml b/.github/workflows/apisec-scan.yml index 5875cc28ae724..166d2f8ee0235 100644 --- a/.github/workflows/apisec-scan.yml +++ b/.github/workflows/apisec-scan.yml @@ -1,4 +1,6 @@ name: APIsec +permissions: + contents: read on: pull_request: From ab7fffd8da41fed1a84a7173198f107490548ed8 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Mon, 13 Oct 2025 08:03:11 +0700 Subject: [PATCH 063/232] Update crates/common/src/contracts.rs Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- crates/common/src/contracts.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/common/src/contracts.rs b/crates/common/src/contracts.rs index d66f340d8c6fc..7bd478a210b3e 100644 --- a/crates/common/src/contracts.rs +++ b/crates/common/src/contracts.rs @@ -163,7 +163,7 @@ impl ContractsByArtifact { None } }) - .min_by(|(score1, _), (score2, _)| score1.partial_cmp(score2).unwrap()) + .min_by(|(score1, _), (score2, _)| score1.partial_cmp(score2).unwrap_or(std::cmp::Ordering::Equal)) .map(|(_, data)| data) } From 6afa4a42b716ac74d0c107f15b9ff887413877b4 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Tue, 14 Oct 2025 00:17:22 +0000 Subject: [PATCH 064/232] Update ci.yml (#107) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .circleci/ci.yml | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/.circleci/ci.yml b/.circleci/ci.yml index b908ef7ada8fb..7293433a50f2d 100644 --- a/.circleci/ci.yml +++ b/.circleci/ci.yml @@ -1,14 +1,32 @@ - build_and_test: +version: 2.1 + +jobs: + build-and-test: docker: - - image: cimg/rust:1.75.0 + - image: cimg/rust:1.88.0 steps: - checkout + - restore_cache: + keys: + - v1-cargo-{{ checksum "Cargo.lock" }} + - v1-cargo- - run: name: "Check formatting" - command: "cargo fmt --all -- --check" + command: cargo fmt -- --check - run: - name: "Run Clippy" - command: "cargo clippy --all-targets -- -D warnings" + name: "Run tests" + command: cargo test + - save_cache: + key: v1-cargo-{{ checksum "Cargo.lock" }} + paths: + - "~/.cargo/bin" + - "~/.cargo/registry/index" + - "~/.cargo/registry/cache" + - "~/.cargo/git/db" + - "target" + - run: + name: "Check formatting" + command: cargo fmt -- --check - run: name: "Run tests" - command: "cargo test --all-features" + command: cargo test From bf979a354ebcd03740d081461860793c38d2244c Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Tue, 14 Oct 2025 02:28:17 +0000 Subject: [PATCH 065/232] Create config.yml (#114) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .circleci/config.yml | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 .circleci/config.yml diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000000000..d5d401c51893c --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,31 @@ +# Use the latest 2.1 version of CircleCI pipeline process engine. +# See: https://circleci.com/docs/configuration-reference +version: 2.1 + +# Define a job to be invoked later in a workflow. +# See: https://circleci.com/docs/jobs-steps/#jobs-overview & https://circleci.com/docs/configuration-reference/#jobs +jobs: + say-hello: + # Specify the execution environment. You can specify an image from Docker Hub or use one of our convenience images from CircleCI's Developer Hub. + # See: https://circleci.com/docs/executor-intro/ & https://circleci.com/docs/configuration-reference/#executor-job + docker: + # Specify the version you desire here + # See: https://circleci.com/developer/images/image/cimg/base + - image: cimg/base:current + + # Add steps to the job + # See: https://circleci.com/docs/jobs-steps/#steps-overview & https://circleci.com/docs/configuration-reference/#steps + steps: + # Checkout the code as the first step. + - checkout + - run: + name: "Say hello" + command: "echo Hello, World!" + +# Orchestrate jobs using workflows +# See: https://circleci.com/docs/workflows/ & https://circleci.com/docs/configuration-reference/#workflows +workflows: + say-hello-workflow: # This is the name of the workflow, feel free to change it to better match your workflow. + # Inside the workflow, you define the jobs you want to run. + jobs: + - say-hello From b95fcbe71c234ad4f7fb16ea331f32e420fb0dbe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Oct 2025 10:20:11 +0700 Subject: [PATCH 066/232] chore(deps): bump github/codeql-action from 3 to 4 (#113) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3 to 4. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/v3...v4) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: '4' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 94526a89f54d4..25e86624d1c8c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -189,12 +189,12 @@ jobs: with: persist-credentials: false - name: Initialize CodeQL - uses: github/codeql-action/init@v3 + uses: github/codeql-action/init@v4 with: languages: ${{ matrix.language }} build-mode: ${{ matrix.build-mode }} - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 + uses: github/codeql-action/analyze@v4 with: category: "/language:${{matrix.language}}" From 857e8adf9d575274aa269cfbc31c79490d35914c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Oct 2025 10:23:20 +0700 Subject: [PATCH 067/232] chore(deps): bump DeterminateSystems/determinate-nix-action (#111) Bumps [DeterminateSystems/determinate-nix-action](https://github.com/determinatesystems/determinate-nix-action) from 3.11.2 to 3.11.3. - [Release notes](https://github.com/determinatesystems/determinate-nix-action/releases) - [Commits](https://github.com/determinatesystems/determinate-nix-action/compare/dbda91f6efef3ee627f56175120aa9543687d830...762d7fdba79d046449732c729c1d3aaad021baa2) --- updated-dependencies: - dependency-name: DeterminateSystems/determinate-nix-action dependency-version: 3.11.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/nix.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index 09810ac02b208..1667f1096deed 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -19,7 +19,7 @@ jobs: contents: write pull-requests: write steps: - - uses: DeterminateSystems/determinate-nix-action@dbda91f6efef3ee627f56175120aa9543687d830 # v3 + - uses: DeterminateSystems/determinate-nix-action@762d7fdba79d046449732c729c1d3aaad021baa2 # v3 - uses: actions/checkout@v5 with: persist-credentials: false @@ -38,7 +38,7 @@ jobs: permissions: contents: read steps: - - uses: DeterminateSystems/determinate-nix-action@dbda91f6efef3ee627f56175120aa9543687d830 # v3 + - uses: DeterminateSystems/determinate-nix-action@762d7fdba79d046449732c729c1d3aaad021baa2 # v3 - uses: actions/checkout@v5 with: persist-credentials: false From 3fa1ae4f94a2bc4067d3dc27e2c561079b59f97e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Oct 2025 10:25:41 +0700 Subject: [PATCH 068/232] chore(deps): bump crate-ci/typos from 1.38.0 to 1.38.1 (#112) Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.38.0 to 1.38.1. - [Release notes](https://github.com/crate-ci/typos/releases) - [Changelog](https://github.com/crate-ci/typos/blob/master/CHANGELOG.md) - [Commits](https://github.com/crate-ci/typos/compare/83157de2df0fa7c7ae20f73f9dbed44c41f2bb64...80c8a4945eec0f6d464eaf9e65ed98ef085283d1) --- updated-dependencies: - dependency-name: crate-ci/typos dependency-version: 1.38.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 25e86624d1c8c..f7e8d00e8cda2 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -92,7 +92,7 @@ jobs: - uses: actions/checkout@v5 with: persist-credentials: false - - uses: crate-ci/typos@83157de2df0fa7c7ae20f73f9dbed44c41f2bb64 # v1 + - uses: crate-ci/typos@80c8a4945eec0f6d464eaf9e65ed98ef085283d1 # v1 clippy: runs-on: depot-ubuntu-latest From 35729e26795c6161c162b1b0dd59db9b07e0f635 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Oct 2025 10:43:48 +0700 Subject: [PATCH 069/232] chore(deps): bump softprops/action-gh-release from 2.3.4 to 2.4.1 (#110) Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 2.3.4 to 2.4.1. - [Release notes](https://github.com/softprops/action-gh-release/releases) - [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md) - [Commits](https://github.com/softprops/action-gh-release/compare/62c96d0c4e8a889135c1f3a25910db8dbe0e85f7...6da8fa9354ddfdc4aeace5fc48d7f679b5214090) --- updated-dependencies: - dependency-name: softprops/action-gh-release dependency-version: 2.4.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 589d38e8014c5..c4d553c80a428 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -267,7 +267,7 @@ jobs: # Creates the release for this specific version - name: Create release - uses: softprops/action-gh-release@62c96d0c4e8a889135c1f3a25910db8dbe0e85f7 # v2.3.4 + uses: softprops/action-gh-release@6da8fa9354ddfdc4aeace5fc48d7f679b5214090 # v2.4.1 with: name: ${{ needs.prepare.outputs.release_name }} tag_name: ${{ needs.prepare.outputs.tag_name }} @@ -282,7 +282,7 @@ jobs: # tagged `nightly` for compatibility with `foundryup` - name: Update nightly release if: ${{ env.IS_NIGHTLY == 'true' }} - uses: softprops/action-gh-release@62c96d0c4e8a889135c1f3a25910db8dbe0e85f7 # v2.3.4 + uses: softprops/action-gh-release@6da8fa9354ddfdc4aeace5fc48d7f679b5214090 # v2.4.1 with: name: "Nightly" tag_name: "nightly" From ee8bebac3a817ad0722e61ac79c727193ec5acd2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 Oct 2025 10:45:19 +0700 Subject: [PATCH 070/232] chore(deps): bump taiki-e/install-action from 2.62.21 to 2.62.28 (#109) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.62.21 to 2.62.28. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/522492a8c115f1b6d4d318581f09638e9442547b...e7ef886cf8f69c25ecef6bbc2858a42e273496ec) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-version: 2.62.28 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/nextest.yml | 2 +- .github/workflows/test.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/nextest.yml b/.github/workflows/nextest.yml index 5d986107519d9..a5513e9398fdc 100644 --- a/.github/workflows/nextest.yml +++ b/.github/workflows/nextest.yml @@ -67,7 +67,7 @@ jobs: toolchain: stable target: ${{ matrix.target }} - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 - - uses: taiki-e/install-action@522492a8c115f1b6d4d318581f09638e9442547b # v2 + - uses: taiki-e/install-action@e7ef886cf8f69c25ecef6bbc2858a42e273496ec # v2 with: tool: nextest diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f7e8d00e8cda2..e0424c485b067 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -159,7 +159,7 @@ jobs: with: toolchain: stable - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 - - uses: taiki-e/install-action@522492a8c115f1b6d4d318581f09638e9442547b # v2 + - uses: taiki-e/install-action@e7ef886cf8f69c25ecef6bbc2858a42e273496ec # v2 with: tool: cargo-hack - uses: mozilla-actions/sccache-action@7d986dd989559c6ecdb630a3fd2557667be217ad # v0.0.9 From f96ff7748a4adf71e1082b02e716da5c4157ecd4 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Tue, 14 Oct 2025 12:25:07 +0000 Subject: [PATCH 071/232] Update test.yml (#115) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .github/workflows/test.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e0424c485b067..94526a89f54d4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -92,7 +92,7 @@ jobs: - uses: actions/checkout@v5 with: persist-credentials: false - - uses: crate-ci/typos@80c8a4945eec0f6d464eaf9e65ed98ef085283d1 # v1 + - uses: crate-ci/typos@83157de2df0fa7c7ae20f73f9dbed44c41f2bb64 # v1 clippy: runs-on: depot-ubuntu-latest @@ -159,7 +159,7 @@ jobs: with: toolchain: stable - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 - - uses: taiki-e/install-action@e7ef886cf8f69c25ecef6bbc2858a42e273496ec # v2 + - uses: taiki-e/install-action@522492a8c115f1b6d4d318581f09638e9442547b # v2 with: tool: cargo-hack - uses: mozilla-actions/sccache-action@7d986dd989559c6ecdb630a3fd2557667be217ad # v0.0.9 @@ -189,12 +189,12 @@ jobs: with: persist-credentials: false - name: Initialize CodeQL - uses: github/codeql-action/init@v4 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} build-mode: ${{ matrix.build-mode }} - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v4 + uses: github/codeql-action/analyze@v3 with: category: "/language:${{matrix.language}}" From 9c9343ad7b53f359ec32c65a31bf69c3f4b208e9 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Tue, 14 Oct 2025 19:31:57 +0700 Subject: [PATCH 072/232] Update crates/doc/src/writer/buf_writer.rs Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- crates/doc/src/writer/buf_writer.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/doc/src/writer/buf_writer.rs b/crates/doc/src/writer/buf_writer.rs index d1e51dfeca6e0..e5dfbbaadce25 100644 --- a/crates/doc/src/writer/buf_writer.rs +++ b/crates/doc/src/writer/buf_writer.rs @@ -213,7 +213,7 @@ impl BufWriter { }); let row = [ - Markdown::Code(¶m_name.unwrap_or("".to_string())).as_doc()?, + Markdown::Code(param_name.as_deref().unwrap_or("")).as_doc()?, comment.unwrap_or_default().replace('\n', " "), ]; self.write_piped(&row.join("|"))?; From fb852fce06ecb0cea856cb1d238697cc6dc74abf Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Wed, 15 Oct 2025 00:25:54 +0700 Subject: [PATCH 073/232] Update config.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .circleci/config.yml | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d5d401c51893c..790c879119cd6 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,31 +1,17 @@ -# Use the latest 2.1 version of CircleCI pipeline process engine. -# See: https://circleci.com/docs/configuration-reference version: 2.1 -# Define a job to be invoked later in a workflow. -# See: https://circleci.com/docs/jobs-steps/#jobs-overview & https://circleci.com/docs/configuration-reference/#jobs jobs: say-hello: - # Specify the execution environment. You can specify an image from Docker Hub or use one of our convenience images from CircleCI's Developer Hub. - # See: https://circleci.com/docs/executor-intro/ & https://circleci.com/docs/configuration-reference/#executor-job - docker: - # Specify the version you desire here - # See: https://circleci.com/developer/images/image/cimg/base + docker: - image: cimg/base:current - - # Add steps to the job - # See: https://circleci.com/docs/jobs-steps/#steps-overview & https://circleci.com/docs/configuration-reference/#steps + steps: - # Checkout the code as the first step. - checkout - run: name: "Say hello" command: "echo Hello, World!" - -# Orchestrate jobs using workflows -# See: https://circleci.com/docs/workflows/ & https://circleci.com/docs/configuration-reference/#workflows + workflows: - say-hello-workflow: # This is the name of the workflow, feel free to change it to better match your workflow. - # Inside the workflow, you define the jobs you want to run. + say-hello-workflow: jobs: - say-hello From 2b20d9d4ccd0e79ba9d3660e172ee455084a76fb Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Wed, 15 Oct 2025 03:31:48 +0700 Subject: [PATCH 074/232] Update and rename config.yml to ci.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .circleci/{config.yml => ci.yml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .circleci/{config.yml => ci.yml} (100%) diff --git a/.circleci/config.yml b/.circleci/ci.yml similarity index 100% rename from .circleci/config.yml rename to .circleci/ci.yml From e2b8aa9d6184931920d28f0cdfc7dfb6f4131871 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Wed, 15 Oct 2025 03:36:47 +0700 Subject: [PATCH 075/232] Rename ci_cargo.yml to ci_v1.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .circleci/{ci_cargo.yml => ci_v1.yml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .circleci/{ci_cargo.yml => ci_v1.yml} (100%) diff --git a/.circleci/ci_cargo.yml b/.circleci/ci_v1.yml similarity index 100% rename from .circleci/ci_cargo.yml rename to .circleci/ci_v1.yml From d4b621fc308e595e484eab989b403c38f36540d8 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Wed, 15 Oct 2025 03:55:28 +0700 Subject: [PATCH 076/232] Update .circleci/ci_v1.yml Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .circleci/ci_v1.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.circleci/ci_v1.yml b/.circleci/ci_v1.yml index 46a18d45a5fca..94bf46b3bb04f 100644 --- a/.circleci/ci_v1.yml +++ b/.circleci/ci_v1.yml @@ -24,12 +24,6 @@ jobs: - "~/.cargo/registry/cache" - "~/.cargo/git/db" - "target" - - run: - name: "Check formatting" - command: cargo fmt -- --check - - run: - name: "Run tests" - command: cargo test workflows: ci: From b5585aebcd03672a0efd9054ce5502d750097c90 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Tue, 14 Oct 2025 21:18:46 +0000 Subject: [PATCH 077/232] Foundry/master (#122) * Create ci_cargo.yml (#72) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Create config.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Update and rename config.yml to ci.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Rename ci_cargo.yml to ci_v1.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Update .circleci/ci_v1.yml Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --------- Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> --- .circleci/ci.yml | 31 +++++++++++++++++++++++++++++++ .circleci/ci_v1.yml | 31 +++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 .circleci/ci.yml create mode 100644 .circleci/ci_v1.yml diff --git a/.circleci/ci.yml b/.circleci/ci.yml new file mode 100644 index 0000000000000..f967cfaa30db5 --- /dev/null +++ b/.circleci/ci.yml @@ -0,0 +1,31 @@ +# Use the latest 2.1 version of CircleCI pipeline process engine. +# See: https://circleci.com/docs/reference/configuration-reference +version: 2.1 + +# Define a job to be invoked later in a workflow. +# See: https://circleci.com/docs/guides/orchestrate/jobs-steps/#jobs-overview & https://circleci.com/docs/reference/configuration-reference/#jobs +jobs: + say-hello: + # Specify the execution environment. You can specify an image from Docker Hub or use one of our convenience images from CircleCI's Developer Hub. + # See: https://circleci.com/docs/guides/execution-managed/executor-intro/ & https://circleci.com/docs/reference/configuration-reference/#executor-job + docker: + # Specify the version you desire here + # See: https://circleci.com/developer/images/image/cimg/base + - image: cimg/base:current + + # Add steps to the job + # See: https://circleci.com/docs/guides/orchestrate/jobs-steps/#steps-overview & https://circleci.com/docs/reference/configuration-reference/#steps + steps: + # Checkout the code as the first step. + - checkout + - run: + name: "Say hello" + command: "echo Hello, World!" + +# Orchestrate jobs using workflows +# See: https://circleci.com/docs/guides/orchestrate/workflows/ & https://circleci.com/docs/reference/configuration-reference/#workflows +workflows: + say-hello-workflow: # This is the name of the workflow, feel free to change it to better match your workflow. + # Inside the workflow, you define the jobs you want to run. + jobs: + - say-hello diff --git a/.circleci/ci_v1.yml b/.circleci/ci_v1.yml new file mode 100644 index 0000000000000..94bf46b3bb04f --- /dev/null +++ b/.circleci/ci_v1.yml @@ -0,0 +1,31 @@ +version: 2.1 + +jobs: + build-and-test: + docker: + - image: cimg/rust:1.88.0 + steps: + - checkout + - restore_cache: + keys: + - v1-cargo-{{ checksum "Cargo.lock" }} + - v1-cargo- + - run: + name: "Check formatting" + command: cargo fmt -- --check + - run: + name: "Run tests" + command: cargo test + - save_cache: + key: v1-cargo-{{ checksum "Cargo.lock" }} + paths: + - "~/.cargo/bin" + - "~/.cargo/registry/index" + - "~/.cargo/registry/cache" + - "~/.cargo/git/db" + - "target" + +workflows: + ci: + jobs: + - build-and-test From b67d5891aa6dee2a15637794483188a656d1852c Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Tue, 14 Oct 2025 21:34:13 +0000 Subject: [PATCH 078/232] Update and rename config.yml to ci_deploy.yml (#123) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .circleci/ci_deploy.yml | 34 ++++++++++++++++++++++++++++++++++ .circleci/config.yml | 17 ----------------- 2 files changed, 34 insertions(+), 17 deletions(-) create mode 100644 .circleci/ci_deploy.yml delete mode 100644 .circleci/config.yml diff --git a/.circleci/ci_deploy.yml b/.circleci/ci_deploy.yml new file mode 100644 index 0000000000000..0c8ae5507187d --- /dev/null +++ b/.circleci/ci_deploy.yml @@ -0,0 +1,34 @@ +version: 2.1 + +jobs: + say-hello: + docker: + - image: cimg/base:current + + steps: + - checkout + - run: + name: "Say hello" + command: "echo Hello, World!" + +workflows: + say-hello-workflow: + jobs: + - say-hello + +- run: + name: Plan a deploy + command: | + circleci run release plan \ + --environment-name="" \ + --component-name="" \ + --target-version="" +# Your job here doing the actual deployment +- run: + name: Update a deploy to SUCCESS + command: circleci run release update --status=SUCCESS + when: on_success +- run: + name: Update planned deploy to FAILED + command: circleci run release update --status=FAILED + when: on_fail diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index 790c879119cd6..0000000000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,17 +0,0 @@ -version: 2.1 - -jobs: - say-hello: - docker: - - image: cimg/base:current - - steps: - - checkout - - run: - name: "Say hello" - command: "echo Hello, World!" - -workflows: - say-hello-workflow: - jobs: - - say-hello From d39b7a5e51705fe2b696f6794e0adfc047309402 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Wed, 15 Oct 2025 09:54:08 +0700 Subject: [PATCH 079/232] Create snyk-container.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .github/workflows/snyk-container.yml | 55 ++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 .github/workflows/snyk-container.yml diff --git a/.github/workflows/snyk-container.yml b/.github/workflows/snyk-container.yml new file mode 100644 index 0000000000000..0db31480beb38 --- /dev/null +++ b/.github/workflows/snyk-container.yml @@ -0,0 +1,55 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +# A sample workflow which checks out the code, builds a container +# image using Docker and scans that image for vulnerabilities using +# Snyk. The results are then uploaded to GitHub Security Code Scanning +# +# For more examples, including how to limit scans to only high-severity +# issues, monitor images for newly disclosed vulnerabilities in Snyk and +# fail PR checks for new vulnerabilities, see https://github.com/snyk/actions/ + +name: Snyk Container + +on: + push: + branches: [ "master" ] + pull_request: + # The branches below must be a subset of the branches above + branches: [ "master" ] + schedule: + - cron: '30 10 * * 1' + +permissions: + contents: read + +jobs: + snyk: + permissions: + contents: read # for actions/checkout to fetch code + security-events: write # for github/codeql-action/upload-sarif to upload SARIF results + actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Build a Docker image + run: docker build -t your/image-to-test . + - name: Run Snyk to check Docker image for vulnerabilities + # Snyk can be used to break the build when it detects vulnerabilities. + # In this case we want to upload the issues to GitHub Code Scanning + continue-on-error: true + uses: snyk/actions/docker@14818c4695ecc4045f33c9cee9e795a788711ca4 + env: + # In order to use the Snyk Action you will need to have a Snyk API token. + # More details in https://github.com/snyk/actions#getting-your-snyk-token + # or you can signup for free at https://snyk.io/login + SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} + with: + image: your/image-to-test + args: --file=Dockerfile + - name: Upload result to GitHub Code Scanning + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: snyk.sarif From a767f09584ca1598d02e8e93dedea07129f88523 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Wed, 15 Oct 2025 09:14:19 +0700 Subject: [PATCH 080/232] Update and rename ci.yml to ci-say-hello.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .circleci/{ci.yml => ci-say-hello.yml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .circleci/{ci.yml => ci-say-hello.yml} (100%) diff --git a/.circleci/ci.yml b/.circleci/ci-say-hello.yml similarity index 100% rename from .circleci/ci.yml rename to .circleci/ci-say-hello.yml From 93f1ac838589770bd4a6826b5807c75cf0961806 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Wed, 15 Oct 2025 09:18:58 +0700 Subject: [PATCH 081/232] Update test.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .github/workflows/test.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 94526a89f54d4..76b4367363adb 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -28,7 +28,7 @@ jobs: docs: runs-on: depot-ubuntu-latest - timeout-minutes: 30 + timeout-minutes: 5 permissions: contents: read steps: @@ -55,7 +55,7 @@ jobs: if: github.ref_name == 'master' && github.event_name == 'push' needs: [docs] runs-on: depot-ubuntu-latest - timeout-minutes: 30 + timeout-minutes: 5 permissions: pages: write id-token: write @@ -69,7 +69,7 @@ jobs: doctest: runs-on: depot-ubuntu-latest - timeout-minutes: 30 + timeout-minutes: 5 permissions: contents: read steps: @@ -85,7 +85,7 @@ jobs: typos: runs-on: depot-ubuntu-latest - timeout-minutes: 30 + timeout-minutes: 5 permissions: contents: read steps: @@ -96,7 +96,7 @@ jobs: clippy: runs-on: depot-ubuntu-latest - timeout-minutes: 30 + timeout-minutes: 5 permissions: contents: read steps: @@ -115,7 +115,7 @@ jobs: rustfmt: runs-on: depot-ubuntu-latest - timeout-minutes: 30 + timeout-minutes: 5 permissions: contents: read steps: @@ -130,7 +130,7 @@ jobs: forge-fmt: runs-on: depot-ubuntu-latest - timeout-minutes: 30 + timeout-minutes: 5 permissions: contents: read steps: @@ -148,7 +148,7 @@ jobs: crate-checks: runs-on: depot-ubuntu-latest - timeout-minutes: 30 + timeout-minutes: 5 permissions: contents: read steps: @@ -213,7 +213,7 @@ jobs: - crate-checks - deny - codeql - timeout-minutes: 30 + timeout-minutes: 5 steps: - name: Decide whether the needed jobs succeeded or failed uses: re-actors/alls-green@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe # release/v1 From cac7793c527951b86839c24d55156f60c27b695c Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Wed, 15 Oct 2025 22:14:25 +0000 Subject: [PATCH 082/232] Create config.ym (#128) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .circleci/config.ym | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 .circleci/config.ym diff --git a/.circleci/config.ym b/.circleci/config.ym new file mode 100644 index 0000000000000..709c9a7474d04 --- /dev/null +++ b/.circleci/config.ym @@ -0,0 +1,26 @@ +# Use the latest 2.1 version of CircleCI pipeline process engine. +# See: https://circleci.com/docs/configuration-reference + +version: 2.1 +executors: + my-custom-executor: + docker: + - image: cimg/base:stable + auth: + # ensure you have first added these secrets + # visit app.circleci.com/settings/project/github/Dargon789/hardhat-project/environment-variables + username: $DOCKER_HUB_USER + password: $DOCKER_HUB_PASSWORD +jobs: + web3-defi-game-project-: + + executor: my-custom-executor + steps: + - checkout + - run: | + # echo Hello, World! + +workflows: + my-custom-workflow: + jobs: + - web3-defi-game-project- From 95d4a0b5ac6da5fefadd287ef1e07f3a07e8104f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 Oct 2025 06:11:14 +0700 Subject: [PATCH 083/232] chore(deps): bump alloy-dyn-abi in the cargo group across 1 directory (#129) Bumps the cargo group with 1 update in the / directory: [alloy-dyn-abi](https://github.com/alloy-rs/core). Updates `alloy-dyn-abi` from 1.4.0 to 1.4.1 - [Release notes](https://github.com/alloy-rs/core/releases) - [Changelog](https://github.com/alloy-rs/core/blob/main/CHANGELOG.md) - [Commits](https://github.com/alloy-rs/core/compare/v1.4.0...v1.4.1) --- updated-dependencies: - dependency-name: alloy-dyn-abi dependency-version: 1.4.1 dependency-type: direct:production dependency-group: cargo ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- Cargo.lock | 36 ++++++++++++++++++------------------ Cargo.toml | 2 +- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2fb563560bbbc..3a48463ff8597 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -133,9 +133,9 @@ dependencies = [ [[package]] name = "alloy-dyn-abi" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6c2905bafc2df7ccd32ca3af13f0b0d82f2e2ff9dfbeb12196c0d978d5c0deb" +checksum = "3fdff496dd4e98a81f4861e66f7eaf5f2488971848bb42d9c892f871730245c8" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -288,9 +288,9 @@ dependencies = [ [[package]] name = "alloy-json-abi" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2acb6637a9c0e1cdf8971e0ced8f3fa34c04c5e9dccf6bb184f6a64fe0e37d8" +checksum = "5513d5e6bd1cba6bdcf5373470f559f320c05c8c59493b6e98912fbe6733943f" dependencies = [ "alloy-primitives", "alloy-sol-type-parser", @@ -383,9 +383,9 @@ dependencies = [ [[package]] name = "alloy-primitives" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b77f7d5e60ad8ae6bd2200b8097919712a07a6db622a4b201e7ead6166f02e5" +checksum = "355bf68a433e0fd7f7d33d5a9fc2583fde70bf5c530f63b80845f8da5505cf28" dependencies = [ "alloy-rlp", "arbitrary", @@ -784,9 +784,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78c84c3637bee9b5c4a4d2b93360ee16553d299c3b932712353caf1cea76d0e6" +checksum = "f3ce480400051b5217f19d6e9a82d9010cdde20f1ae9c00d53591e4a1afbb312" dependencies = [ "alloy-sol-macro-expander", "alloy-sol-macro-input", @@ -798,9 +798,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro-expander" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a882aa4e1790063362434b9b40d358942b188477ac1c44cfb8a52816ffc0cc17" +checksum = "6d792e205ed3b72f795a8044c52877d2e6b6e9b1d13f431478121d8d4eaa9028" dependencies = [ "alloy-json-abi", "alloy-sol-macro-input", @@ -817,9 +817,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro-input" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18e5772107f9bb265d8d8c86e0733937bb20d0857ea5425b1b6ddf51a9804042" +checksum = "0bd1247a8f90b465ef3f1207627547ec16940c35597875cdc09c49d58b19693c" dependencies = [ "alloy-json-abi", "const-hex", @@ -835,9 +835,9 @@ dependencies = [ [[package]] name = "alloy-sol-type-parser" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e188b939aa4793edfaaa099cb1be4e620036a775b4bdf24fdc56f1cd6fd45890" +checksum = "954d1b2533b9b2c7959652df3076954ecb1122a28cc740aa84e7b0a49f6ac0a9" dependencies = [ "serde", "winnow", @@ -845,9 +845,9 @@ dependencies = [ [[package]] name = "alloy-sol-types" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3c8a9a909872097caffc05df134e5ef2253a1cdb56d3a9cf0052a042ac763f9" +checksum = "70319350969a3af119da6fb3e9bddb1bce66c9ea933600cb297c8b1850ad2a3c" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -9674,9 +9674,9 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2375c17f6067adc651d8c2c51658019cef32edfff4a982adaf1d7fd1c039f08b" +checksum = "ff790eb176cc81bb8936aed0f7b9f14fc4670069a2d371b3e3b0ecce908b2cb3" dependencies = [ "paste", "proc-macro2", diff --git a/Cargo.toml b/Cargo.toml index a69d750b6eb2a..6c29441366881 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -259,7 +259,7 @@ alloy-hardforks = { version = "0.3.2", default-features = false } alloy-op-hardforks = { version = "0.3.2", default-features = false } ## alloy-core -alloy-dyn-abi = "1.3.1" +alloy-dyn-abi = "1.4.1" alloy-json-abi = "1.3.0" alloy-primitives = { version = "1.3.1", features = [ "getrandom", From 0a0a62a2f9db40b779cbf77b8c074e464c916a06 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Thu, 16 Oct 2025 00:25:27 +0000 Subject: [PATCH 084/232] Create cargo.yml (#74) (#130) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .circleci/cargo.yml | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 .circleci/cargo.yml diff --git a/.circleci/cargo.yml b/.circleci/cargo.yml new file mode 100644 index 0000000000000..d7a82b5c93b6e --- /dev/null +++ b/.circleci/cargo.yml @@ -0,0 +1,37 @@ +version: 2.1 + +jobs: + build-and-test: + docker: + - image: cimg/rust:1.89.0 + steps: + - checkout + - restore_cache: + keys: + - v1-cargo-{{ checksum "Cargo.lock" }} + - v1-cargo- + - run: + name: "Check formatting" + command: cargo fmt -- --check + - run: + name: "Run tests" + command: cargo test + - save_cache: + key: v1-cargo-{{ checksum "Cargo.lock" }} + paths: + - "~/.cargo/bin" + - "~/.cargo/registry/index" + - "~/.cargo/registry/cache" + - "~/.cargo/git/db" + - "target" + - run: + name: "Check formatting" + command: cargo fmt -- --check + - run: + name: "Run tests" + command: cargo test + +workflows: + ci: + jobs: + - build-and-test From 343afb6fad0635fff7f09f7f6580276f608bdff5 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Thu, 16 Oct 2025 14:01:53 +0700 Subject: [PATCH 085/232] Fix typo in CircleCI config file name Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .circleci/{config.ym => config.yml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .circleci/{config.ym => config.yml} (100%) diff --git a/.circleci/config.ym b/.circleci/config.yml similarity index 100% rename from .circleci/config.ym rename to .circleci/config.yml From 9f64c477f81e02b10dc2bc39f62a86f20de8e72f Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Thu, 16 Oct 2025 14:13:58 +0700 Subject: [PATCH 086/232] Update .circleci/config.yml Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .circleci/config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 709c9a7474d04..3b59d59e57c17 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -17,6 +17,7 @@ jobs: executor: my-custom-executor steps: - checkout + - run: echo "Build started" - run: | # echo Hello, World! From 5b4a4997ef80f7f75dda19032c4f879f4905ead8 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Thu, 16 Oct 2025 16:58:49 +0700 Subject: [PATCH 087/232] Fix formatting in cargo.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> From 8d1f66a47982e14d54d63b48e762ecd9b6f7cf8e Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Thu, 16 Oct 2025 17:00:26 +0700 Subject: [PATCH 088/232] Fix indentation for on_fail condition in CI config Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> From 93a4079269bcc9e83abb5c4da5d2b3460e8a8075 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Thu, 16 Oct 2025 17:00:48 +0700 Subject: [PATCH 089/232] Fix indentation in CircleCI configuration Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> From c35961b39146e60ad4f76f912cc383e5852842c7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 Oct 2025 20:07:12 +0700 Subject: [PATCH 090/232] chore(deps): bump taiki-e/install-action from 2.62.21 to 2.62.31 (#139) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.62.21 to 2.62.31. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/v2.62.21...0005e0116e92d8489d8d96fbff83f061c79ba95a) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-version: 2.62.31 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/nextest.yml | 2 +- .github/workflows/test.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/nextest.yml b/.github/workflows/nextest.yml index a5513e9398fdc..d39b597f7613e 100644 --- a/.github/workflows/nextest.yml +++ b/.github/workflows/nextest.yml @@ -67,7 +67,7 @@ jobs: toolchain: stable target: ${{ matrix.target }} - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 - - uses: taiki-e/install-action@e7ef886cf8f69c25ecef6bbc2858a42e273496ec # v2 + - uses: taiki-e/install-action@0005e0116e92d8489d8d96fbff83f061c79ba95a # v2 with: tool: nextest diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 76b4367363adb..aa505a05a8382 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -159,7 +159,7 @@ jobs: with: toolchain: stable - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 - - uses: taiki-e/install-action@522492a8c115f1b6d4d318581f09638e9442547b # v2 + - uses: taiki-e/install-action@0005e0116e92d8489d8d96fbff83f061c79ba95a # v2 with: tool: cargo-hack - uses: mozilla-actions/sccache-action@7d986dd989559c6ecdb630a3fd2557667be217ad # v0.0.9 From 4a977cd7b1d2aebd2762d9670975d40e1c9e0fe1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 Oct 2025 20:24:58 +0700 Subject: [PATCH 091/232] chore(deps): bump github/codeql-action from 3 to 4 (#138) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3 to 4. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/v3...v4) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: '4' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/snyk-container.yml | 2 +- .github/workflows/test.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/snyk-container.yml b/.github/workflows/snyk-container.yml index 0db31480beb38..171f2aabfbfb1 100644 --- a/.github/workflows/snyk-container.yml +++ b/.github/workflows/snyk-container.yml @@ -50,6 +50,6 @@ jobs: image: your/image-to-test args: --file=Dockerfile - name: Upload result to GitHub Code Scanning - uses: github/codeql-action/upload-sarif@v3 + uses: github/codeql-action/upload-sarif@v4 with: sarif_file: snyk.sarif diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index aa505a05a8382..1f16e1d9964b1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -189,12 +189,12 @@ jobs: with: persist-credentials: false - name: Initialize CodeQL - uses: github/codeql-action/init@v3 + uses: github/codeql-action/init@v4 with: languages: ${{ matrix.language }} build-mode: ${{ matrix.build-mode }} - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 + uses: github/codeql-action/analyze@v4 with: category: "/language:${{matrix.language}}" From 1c660a0d0c1f75f90876e4d55f3f2228bb2a37aa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 Oct 2025 09:47:02 +0000 Subject: [PATCH 092/232] chore(deps): bump snyk/actions Bumps [snyk/actions](https://github.com/snyk/actions) from 14818c4695ecc4045f33c9cee9e795a788711ca4 to 9adf32b1121593767fc3c057af55b55db032dc04. - [Release notes](https://github.com/snyk/actions/releases) - [Commits](https://github.com/snyk/actions/compare/14818c4695ecc4045f33c9cee9e795a788711ca4...9adf32b1121593767fc3c057af55b55db032dc04) --- updated-dependencies: - dependency-name: snyk/actions dependency-version: 9adf32b1121593767fc3c057af55b55db032dc04 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- .github/workflows/snyk-container.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/snyk-container.yml b/.github/workflows/snyk-container.yml index 171f2aabfbfb1..3c3a0f30b84e3 100644 --- a/.github/workflows/snyk-container.yml +++ b/.github/workflows/snyk-container.yml @@ -40,7 +40,7 @@ jobs: # Snyk can be used to break the build when it detects vulnerabilities. # In this case we want to upload the issues to GitHub Code Scanning continue-on-error: true - uses: snyk/actions/docker@14818c4695ecc4045f33c9cee9e795a788711ca4 + uses: snyk/actions/docker@9adf32b1121593767fc3c057af55b55db032dc04 env: # In order to use the Snyk Action you will need to have a Snyk API token. # More details in https://github.com/snyk/actions#getting-your-snyk-token From d287039817a741b53e724d4dacd0a0d4ba496eb7 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Thu, 16 Oct 2025 21:02:39 +0700 Subject: [PATCH 093/232] Update CircleCI config with comments and formatting Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .circleci/config.yml | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 790c879119cd6..d5d401c51893c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,17 +1,31 @@ +# Use the latest 2.1 version of CircleCI pipeline process engine. +# See: https://circleci.com/docs/configuration-reference version: 2.1 +# Define a job to be invoked later in a workflow. +# See: https://circleci.com/docs/jobs-steps/#jobs-overview & https://circleci.com/docs/configuration-reference/#jobs jobs: say-hello: - docker: + # Specify the execution environment. You can specify an image from Docker Hub or use one of our convenience images from CircleCI's Developer Hub. + # See: https://circleci.com/docs/executor-intro/ & https://circleci.com/docs/configuration-reference/#executor-job + docker: + # Specify the version you desire here + # See: https://circleci.com/developer/images/image/cimg/base - image: cimg/base:current - + + # Add steps to the job + # See: https://circleci.com/docs/jobs-steps/#steps-overview & https://circleci.com/docs/configuration-reference/#steps steps: + # Checkout the code as the first step. - checkout - run: name: "Say hello" command: "echo Hello, World!" - + +# Orchestrate jobs using workflows +# See: https://circleci.com/docs/workflows/ & https://circleci.com/docs/configuration-reference/#workflows workflows: - say-hello-workflow: + say-hello-workflow: # This is the name of the workflow, feel free to change it to better match your workflow. + # Inside the workflow, you define the jobs you want to run. jobs: - say-hello From 4934b0283692720e702a258ee5300a62bd25005e Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Fri, 17 Oct 2025 00:17:59 +0700 Subject: [PATCH 094/232] Update config.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .circleci/config.yml | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 3b59d59e57c17..f967cfaa30db5 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,27 +1,31 @@ # Use the latest 2.1 version of CircleCI pipeline process engine. -# See: https://circleci.com/docs/configuration-reference - +# See: https://circleci.com/docs/reference/configuration-reference version: 2.1 -executors: - my-custom-executor: - docker: - - image: cimg/base:stable - auth: - # ensure you have first added these secrets - # visit app.circleci.com/settings/project/github/Dargon789/hardhat-project/environment-variables - username: $DOCKER_HUB_USER - password: $DOCKER_HUB_PASSWORD + +# Define a job to be invoked later in a workflow. +# See: https://circleci.com/docs/guides/orchestrate/jobs-steps/#jobs-overview & https://circleci.com/docs/reference/configuration-reference/#jobs jobs: - web3-defi-game-project-: + say-hello: + # Specify the execution environment. You can specify an image from Docker Hub or use one of our convenience images from CircleCI's Developer Hub. + # See: https://circleci.com/docs/guides/execution-managed/executor-intro/ & https://circleci.com/docs/reference/configuration-reference/#executor-job + docker: + # Specify the version you desire here + # See: https://circleci.com/developer/images/image/cimg/base + - image: cimg/base:current - executor: my-custom-executor + # Add steps to the job + # See: https://circleci.com/docs/guides/orchestrate/jobs-steps/#steps-overview & https://circleci.com/docs/reference/configuration-reference/#steps steps: + # Checkout the code as the first step. - checkout - - run: echo "Build started" - - run: | - # echo Hello, World! + - run: + name: "Say hello" + command: "echo Hello, World!" +# Orchestrate jobs using workflows +# See: https://circleci.com/docs/guides/orchestrate/workflows/ & https://circleci.com/docs/reference/configuration-reference/#workflows workflows: - my-custom-workflow: + say-hello-workflow: # This is the name of the workflow, feel free to change it to better match your workflow. + # Inside the workflow, you define the jobs you want to run. jobs: - - web3-defi-game-project- + - say-hello From 880e28435b0ef38d85f57279df2d33839dfabfef Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Fri, 17 Oct 2025 00:49:41 +0000 Subject: [PATCH 095/232] Update and rename ci-say-hello.yml to ci-web3-defi-gamefi.yml (#154) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .circleci/ci-say-hello.yml | 31 ------------------------------- .circleci/ci-web3-defi-gamefi.yml | 26 ++++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 31 deletions(-) delete mode 100644 .circleci/ci-say-hello.yml create mode 100644 .circleci/ci-web3-defi-gamefi.yml diff --git a/.circleci/ci-say-hello.yml b/.circleci/ci-say-hello.yml deleted file mode 100644 index f967cfaa30db5..0000000000000 --- a/.circleci/ci-say-hello.yml +++ /dev/null @@ -1,31 +0,0 @@ -# Use the latest 2.1 version of CircleCI pipeline process engine. -# See: https://circleci.com/docs/reference/configuration-reference -version: 2.1 - -# Define a job to be invoked later in a workflow. -# See: https://circleci.com/docs/guides/orchestrate/jobs-steps/#jobs-overview & https://circleci.com/docs/reference/configuration-reference/#jobs -jobs: - say-hello: - # Specify the execution environment. You can specify an image from Docker Hub or use one of our convenience images from CircleCI's Developer Hub. - # See: https://circleci.com/docs/guides/execution-managed/executor-intro/ & https://circleci.com/docs/reference/configuration-reference/#executor-job - docker: - # Specify the version you desire here - # See: https://circleci.com/developer/images/image/cimg/base - - image: cimg/base:current - - # Add steps to the job - # See: https://circleci.com/docs/guides/orchestrate/jobs-steps/#steps-overview & https://circleci.com/docs/reference/configuration-reference/#steps - steps: - # Checkout the code as the first step. - - checkout - - run: - name: "Say hello" - command: "echo Hello, World!" - -# Orchestrate jobs using workflows -# See: https://circleci.com/docs/guides/orchestrate/workflows/ & https://circleci.com/docs/reference/configuration-reference/#workflows -workflows: - say-hello-workflow: # This is the name of the workflow, feel free to change it to better match your workflow. - # Inside the workflow, you define the jobs you want to run. - jobs: - - say-hello diff --git a/.circleci/ci-web3-defi-gamefi.yml b/.circleci/ci-web3-defi-gamefi.yml new file mode 100644 index 0000000000000..edb6605e3f101 --- /dev/null +++ b/.circleci/ci-web3-defi-gamefi.yml @@ -0,0 +1,26 @@ +# Use the latest 2.1 version of CircleCI pipeline process engine. +# See: https://circleci.com/docs/configuration-reference + +version: 2.1 +executors: + my-custom-executor: + docker: + - image: cimg/base:stable + auth: + # ensure you have first added these secrets + # visit app.circleci.com/settings/project/github/Dargon789/foundry/environment-variables + username: $DOCKER_HUB_USER + password: $DOCKER_HUB_PASSWORD +jobs: + web3-defi-game-project-: + + executor: my-custom-executor + steps: + - checkout + - run: | + # echo Hello, World! + +workflows: + my-custom-workflow: + jobs: + - web3-defi-game-project- From 78de4afcd8c43817a445010eca9d771e3e87f07b Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Fri, 17 Oct 2025 04:30:24 +0000 Subject: [PATCH 096/232] Delete .circleci/ci-web3-defi-gamefi.yml (#155) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .circleci/ci-web3-defi-gamefi.yml | 26 -------------------------- 1 file changed, 26 deletions(-) delete mode 100644 .circleci/ci-web3-defi-gamefi.yml diff --git a/.circleci/ci-web3-defi-gamefi.yml b/.circleci/ci-web3-defi-gamefi.yml deleted file mode 100644 index edb6605e3f101..0000000000000 --- a/.circleci/ci-web3-defi-gamefi.yml +++ /dev/null @@ -1,26 +0,0 @@ -# Use the latest 2.1 version of CircleCI pipeline process engine. -# See: https://circleci.com/docs/configuration-reference - -version: 2.1 -executors: - my-custom-executor: - docker: - - image: cimg/base:stable - auth: - # ensure you have first added these secrets - # visit app.circleci.com/settings/project/github/Dargon789/foundry/environment-variables - username: $DOCKER_HUB_USER - password: $DOCKER_HUB_PASSWORD -jobs: - web3-defi-game-project-: - - executor: my-custom-executor - steps: - - checkout - - run: | - # echo Hello, World! - -workflows: - my-custom-workflow: - jobs: - - web3-defi-game-project- From 23811a7b17a1358e75fa611d4af534e7cddeb603 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Fri, 17 Oct 2025 07:19:43 +0000 Subject: [PATCH 097/232] Delete .circleci/ci_deploy.yml (#158) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .circleci/ci_deploy.yml | 34 ---------------------------------- 1 file changed, 34 deletions(-) delete mode 100644 .circleci/ci_deploy.yml diff --git a/.circleci/ci_deploy.yml b/.circleci/ci_deploy.yml deleted file mode 100644 index 0c8ae5507187d..0000000000000 --- a/.circleci/ci_deploy.yml +++ /dev/null @@ -1,34 +0,0 @@ -version: 2.1 - -jobs: - say-hello: - docker: - - image: cimg/base:current - - steps: - - checkout - - run: - name: "Say hello" - command: "echo Hello, World!" - -workflows: - say-hello-workflow: - jobs: - - say-hello - -- run: - name: Plan a deploy - command: | - circleci run release plan \ - --environment-name="" \ - --component-name="" \ - --target-version="" -# Your job here doing the actual deployment -- run: - name: Update a deploy to SUCCESS - command: circleci run release update --status=SUCCESS - when: on_success -- run: - name: Update planned deploy to FAILED - command: circleci run release update --status=FAILED - when: on_fail From cc3940779716d5a91105941c16faea922f1d0b0e Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Fri, 17 Oct 2025 07:22:09 +0000 Subject: [PATCH 098/232] Delete .circleci/cargo.yml (#159) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .circleci/cargo.yml | 37 ------------------------------------- 1 file changed, 37 deletions(-) delete mode 100644 .circleci/cargo.yml diff --git a/.circleci/cargo.yml b/.circleci/cargo.yml deleted file mode 100644 index d7a82b5c93b6e..0000000000000 --- a/.circleci/cargo.yml +++ /dev/null @@ -1,37 +0,0 @@ -version: 2.1 - -jobs: - build-and-test: - docker: - - image: cimg/rust:1.89.0 - steps: - - checkout - - restore_cache: - keys: - - v1-cargo-{{ checksum "Cargo.lock" }} - - v1-cargo- - - run: - name: "Check formatting" - command: cargo fmt -- --check - - run: - name: "Run tests" - command: cargo test - - save_cache: - key: v1-cargo-{{ checksum "Cargo.lock" }} - paths: - - "~/.cargo/bin" - - "~/.cargo/registry/index" - - "~/.cargo/registry/cache" - - "~/.cargo/git/db" - - "target" - - run: - name: "Check formatting" - command: cargo fmt -- --check - - run: - name: "Run tests" - command: cargo test - -workflows: - ci: - jobs: - - build-and-test From aa9ac06c9c3303de0af9c42c3bd399f6714be098 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 Oct 2025 18:43:53 +0700 Subject: [PATCH 099/232] chore(deps): bump taiki-e/install-action from 2.62.31 to 2.62.33 (#162) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.62.31 to 2.62.33. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/0005e0116e92d8489d8d96fbff83f061c79ba95a...e43a5023a747770bfcb71ae048541a681714b951) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-version: 2.62.33 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/nextest.yml | 2 +- .github/workflows/test.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/nextest.yml b/.github/workflows/nextest.yml index d39b597f7613e..3d7ef42941deb 100644 --- a/.github/workflows/nextest.yml +++ b/.github/workflows/nextest.yml @@ -67,7 +67,7 @@ jobs: toolchain: stable target: ${{ matrix.target }} - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 - - uses: taiki-e/install-action@0005e0116e92d8489d8d96fbff83f061c79ba95a # v2 + - uses: taiki-e/install-action@e43a5023a747770bfcb71ae048541a681714b951 # v2 with: tool: nextest diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1f16e1d9964b1..e71c1d2f993e3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -159,7 +159,7 @@ jobs: with: toolchain: stable - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 - - uses: taiki-e/install-action@0005e0116e92d8489d8d96fbff83f061c79ba95a # v2 + - uses: taiki-e/install-action@e43a5023a747770bfcb71ae048541a681714b951 # v2 with: tool: cargo-hack - uses: mozilla-actions/sccache-action@7d986dd989559c6ecdb630a3fd2557667be217ad # v0.0.9 From 93e0c5525c67f81ee0ca78f773b5d22e24a9b117 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 Oct 2025 18:46:43 +0700 Subject: [PATCH 100/232] chore(deps): bump actions/checkout from 4 to 5 (#163) Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/snyk-container.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/snyk-container.yml b/.github/workflows/snyk-container.yml index 3c3a0f30b84e3..10ac023cf51fc 100644 --- a/.github/workflows/snyk-container.yml +++ b/.github/workflows/snyk-container.yml @@ -33,7 +33,7 @@ jobs: actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Build a Docker image run: docker build -t your/image-to-test . - name: Run Snyk to check Docker image for vulnerabilities From 07b64156d78ae32bf392635e282bc71e2d3d347e Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Fri, 17 Oct 2025 12:50:52 +0000 Subject: [PATCH 101/232] Merge branch 'foundry-rs:master' (#164) * Create ci_cargo.yml (#72) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Create config.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Rename ci_cargo.yml to cargo.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * fix(fmt): handle trailing coments between base contracts (#12127) * fix(fmt): account for ternary operators when estimating size * fix(fmt): handle comments between inherited base contracts * test: layout + base inheritance * feat(forge): add bypass prevrandao (#12125) * feat(forge): add bypass prevrandao * Update crates/evm/networks/src/lib.rs Co-authored-by: 0xrusowsky <90208954+0xrusowsky@users.noreply.github.com> * changes after review: remove duped code --------- Co-authored-by: 0xrusowsky <90208954+0xrusowsky@users.noreply.github.com> * fix(fmt): filter libs when recursing (#12119) * fix(fmt): account for ternary operators when estimating size * fix(fmt): filter libs when recursing * style: clippy * test: wipe contracts before formatting * test: explicitly test ignore * fix(fmt): break try stmts in a fn header-like fashion (#12131) * chore(deps): bump softprops/action-gh-release from 2.3.4 to 2.4.1 Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 2.3.4 to 2.4.1. - [Release notes](https://github.com/softprops/action-gh-release/releases) - [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md) - [Commits](https://github.com/softprops/action-gh-release/compare/62c96d0c4e8a889135c1f3a25910db8dbe0e85f7...6da8fa9354ddfdc4aeace5fc48d7f679b5214090) --- updated-dependencies: - dependency-name: softprops/action-gh-release dependency-version: 2.4.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * chore(deps): bump taiki-e/install-action from 2.62.28 to 2.62.33 (#161) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.62.28 to 2.62.33. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/e7ef886cf8f69c25ecef6bbc2858a42e273496ec...e43a5023a747770bfcb71ae048541a681714b951) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-version: 2.62.33 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --------- Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Signed-off-by: dependabot[bot] Co-authored-by: 0xrusowsky <90208954+0xrusowsky@users.noreply.github.com> Co-authored-by: grandizzy <38490174+grandizzy@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .circleci/cargo.yml | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 .circleci/cargo.yml diff --git a/.circleci/cargo.yml b/.circleci/cargo.yml new file mode 100644 index 0000000000000..46a18d45a5fca --- /dev/null +++ b/.circleci/cargo.yml @@ -0,0 +1,37 @@ +version: 2.1 + +jobs: + build-and-test: + docker: + - image: cimg/rust:1.88.0 + steps: + - checkout + - restore_cache: + keys: + - v1-cargo-{{ checksum "Cargo.lock" }} + - v1-cargo- + - run: + name: "Check formatting" + command: cargo fmt -- --check + - run: + name: "Run tests" + command: cargo test + - save_cache: + key: v1-cargo-{{ checksum "Cargo.lock" }} + paths: + - "~/.cargo/bin" + - "~/.cargo/registry/index" + - "~/.cargo/registry/cache" + - "~/.cargo/git/db" + - "target" + - run: + name: "Check formatting" + command: cargo fmt -- --check + - run: + name: "Run tests" + command: cargo test + +workflows: + ci: + jobs: + - build-and-test From 9f4f6848a6f83c0e785573833b89471bcc08e048 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Fri, 17 Oct 2025 15:56:21 +0000 Subject: [PATCH 102/232] fix(anvil): always disable nonce check (foundry-rs#12144) (#165) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * test: refactor testdata/ tests to be run in `forge test` (#12049) * test: run forge test on testdata/ * chore: refactor to use common Test contract * chore: disable testGasMeteringExternal, via-ir * test: rm unused repros * fix: paths * upd * fmt * fix more tests * test: turn testNonExistingContractRevert into expectRevert * fix some more paths * legacy assertions * compile paris with paris * fix: set configs for fs tests * fix remaining paths in cheats * restrict fs permissions * fix: set runtime evm_version too * fix vyper * fix: a couple of repros * fix: we have storage layouts * fix: 3223, 3674: set sender * reorder * feat: move repros expected failures to snapshots * feat: migrate remaining repros tests * feat: rm migrated files * skip testRevertIfGetUnlinked * move expected core/ failures * upd * move logs/ * move all forgetest tests from it/ to cli/ * fix fork test * move trace/ * tmp: move fuzz/invariant out of fuzz/ * move fuzz/ * forge fmt * wips * fix: both vyper and paris; set src/ * canon * lib log * logs * Revert "fix: set runtime evm_version too" This reverts commit 7ca544b10047f608d57c74fb3500a5fbe7e2650e. Contract-level inline config will set evm version for libraries too, which means we fail on deploying libraries that are compiled with newer evm version. * fix: set evm version where needed, per test function * test: reduce gas wastage * chore: clippy * invariant mod.rs * test: fix linking tests with new utils * redact_with * Revert "wips" This reverts commit ee2c17a3023ca7ce8e7effccf0ea0a0f28f6e510. * migrate invariant/target{,Abi} * migrate InvariantAfterInvariant.t.sol * migrate InvariantAssume.t.sol * migrate InvariantCalldataDictionary.t.sol, more test utils * migrate InvariantCustomError.t.sol * migrate InvariantExcludedSenders.t.sol * migrate InvariantFixtures.t.sol * migrate InvariantHandlerFailure.t.sol * interlude: forgot to use a new file * migrate InvariantInnerContract.t.sol * migrate InvariantPreserveState.t.sol * migrate InvariantReentrancy.t.sol * migrate InvariantRollFork.t.sol * migrate InvariantScrapeValues.t.sol * migrate InvariantSequenceNoReverts.t.sol * migrate InvariantShrinkBigSequence.t.sol * migrate InvariantShrinkFailOnRevert.t.sol * migrate InvariantShrinkWithAssert.t.sol * migrate InvariantTest1.t.sol * fix InvariantInnerContract.t.sol * update new Rlp test * com * better com * nuke tests/it * test: fix testdata paths in script tester * test: fix relative paths in test_cmd * test: redact more in issue_2851 * fix: copy testdata correctly * trace addrs * manual retry logic with --retry * fix nondeterministic output * debug: fs lock error context * test: fix project root for windows * test: skip project root test if unset * normalize both * typo * Revert "typo" This reverts commit 402bea105c6f38b82664b50ca854f95e456df795. * Revert "debug: fs lock error context" This reverts commit e5caeddd1e4cb457d7b24d7d7fdfdb370e2feabf. * fix * fix: locked_write_line for windows * chore: clippy * fmt * chore: speed up fuzzed_selected_targets * other way * fix nondeterministic output 2 * fix: disable persistence * test: revert old via-ir * ci: tweak cache key * do not run trace test when isolate --------- Co-authored-by: grandizzy * fix(anvil): always disable nonce check (#12144) * deps: bump deps (#12149) * deps: bump deps 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude * minimum Cargo.lock --------- Co-authored-by: rplusq Co-authored-by: Claude Co-authored-by: DaniPopes <57450786+DaniPopes@users.noreply.github.com> --------- Co-authored-by: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Co-authored-by: grandizzy Co-authored-by: grandizzy <38490174+grandizzy@users.noreply.github.com> Co-authored-by: Rafael Quintero <32346241+rplusq@users.noreply.github.com> Co-authored-by: rplusq Co-authored-by: Claude --- .github/workflows/nextest.yml | 5 +- Cargo.lock | 150 +- Cargo.toml | 48 +- crates/anvil/src/eth/backend/mem/mod.rs | 13 +- crates/cheatcodes/spec/src/lib.rs | 3 +- crates/chisel/src/source.rs | 2 +- crates/common/src/fs.rs | 43 +- crates/forge/tests/cli/test_cmd/core.rs | 142 ++ crates/forge/tests/cli/test_cmd/fuzz.rs | 735 +++++++++ .../tests/cli/test_cmd/invariant/common.rs | 1424 +++++++++++++++++ .../test_cmd/invariant/mod.rs} | 708 +------- .../tests/cli/test_cmd/invariant/storage.rs | 19 +- .../tests/cli/test_cmd/invariant/target.rs | 766 +++++++++ crates/forge/tests/cli/test_cmd/logs.rs | 756 +++++++++ .../cli/{test_cmd.rs => test_cmd/mod.rs} | 62 +- .../forge/tests/cli/test_cmd/repros.rs | 447 +++++- .../forge/tests/{it => cli/test_cmd}/spec.rs | 13 +- .../forge/tests/{it => cli/test_cmd}/table.rs | 0 crates/forge/tests/cli/test_cmd/trace.rs | 397 +++++ crates/forge/tests/it/cheats.rs | 112 -- crates/forge/tests/it/config.rs | 170 -- crates/forge/tests/it/core.rs | 829 ---------- crates/forge/tests/it/fork.rs | 129 -- crates/forge/tests/it/fs.rs | 23 - crates/forge/tests/it/fuzz.rs | 496 ------ crates/forge/tests/it/inline.rs | 70 - crates/forge/tests/it/main.rs | 14 - crates/forge/tests/it/repros.rs | 411 ----- crates/forge/tests/it/test_helpers.rs | 283 ---- crates/forge/tests/it/vyper.rs | 10 - crates/linking/src/lib.rs | 15 +- crates/test-utils/src/rpc.rs | 20 +- crates/test-utils/src/script.rs | 25 +- crates/test-utils/src/util.rs | 71 +- testdata/default/cheats/AccessList.t.sol | 8 +- testdata/default/cheats/Addr.t.sol | 7 +- .../default/cheats/ArbitraryStorage.t.sol | 22 +- testdata/default/cheats/Assert.t.sol | 7 +- testdata/default/cheats/Assume.t.sol | 7 +- testdata/default/cheats/AssumeNoRevert.t.sol | 18 +- testdata/default/cheats/AttachBlob.t.sol | 6 +- .../default/cheats/AttachDelegation.t.sol | 6 +- testdata/default/cheats/Bank.t.sol | 7 +- testdata/default/cheats/Base64.t.sol | 8 +- testdata/default/cheats/BlobBaseFee.t.sol | 7 +- testdata/default/cheats/Blobhashes.t.sol | 7 +- testdata/default/cheats/Broadcast.t.sol | 56 +- .../cheats/BroadcastRawTransaction.t.sol | 11 +- testdata/default/cheats/ChainId.t.sol | 7 +- testdata/default/cheats/CloneAccount.t.sol | 7 +- testdata/default/cheats/Cool.t.sol | 6 +- testdata/default/cheats/CopyStorage.t.sol | 10 +- testdata/default/cheats/Deal.t.sol | 7 +- testdata/default/cheats/DeployCode.t.sol | 7 +- testdata/default/cheats/Derive.t.sol | 7 +- testdata/default/cheats/EnsNamehash.t.sol | 7 +- testdata/default/cheats/Env.t.sol | 7 +- testdata/default/cheats/Etch.t.sol | 7 +- testdata/default/cheats/ExpectCall.t.sol | 15 +- testdata/default/cheats/ExpectCreate.t.sol | 6 +- testdata/default/cheats/ExpectEmit.t.sol | 9 +- testdata/default/cheats/ExpectRevert.t.sol | 19 +- testdata/default/cheats/Fee.t.sol | 7 +- testdata/default/cheats/Ffi.t.sol | 7 +- testdata/default/cheats/Fork.t.sol | 6 +- testdata/default/cheats/Fork2.t.sol | 15 +- testdata/default/cheats/Fs.t.sol | 14 +- testdata/default/cheats/GasMetering.t.sol | 8 +- testdata/default/cheats/GetArtifactPath.t.sol | 12 +- .../default/cheats/GetBlockTimestamp.t.sol | 7 +- testdata/default/cheats/GetChain.t.sol | 7 +- testdata/default/cheats/GetCode.t.sol | 8 +- testdata/default/cheats/GetDeployedCode.t.sol | 7 +- .../default/cheats/GetFoundryVersion.t.sol | 7 +- testdata/default/cheats/GetLabel.t.sol | 7 +- testdata/default/cheats/GetNonce.t.sol | 7 +- .../default/cheats/GetRawBlockHeader.t.sol | 7 +- testdata/default/cheats/GetStorageSlots.t.sol | 6 +- testdata/default/cheats/Json.t.sol | 11 +- testdata/default/cheats/Label.t.sol | 7 +- testdata/default/cheats/Load.t.sol | 6 +- testdata/default/cheats/Mapping.t.sol | 7 +- testdata/default/cheats/MemSafety.t.sol | 7 +- testdata/default/cheats/MockCall.t.sol | 11 +- testdata/default/cheats/MockCalls.t.sol | 7 +- testdata/default/cheats/MockFunction.t.sol | 6 +- testdata/default/cheats/Nonce.t.sol | 8 +- testdata/default/cheats/Parse.t.sol | 7 +- testdata/default/cheats/Prank.t.sol | 15 +- testdata/default/cheats/Prevrandao.t.sol | 7 +- testdata/default/cheats/ProjectRoot.t.sol | 20 +- testdata/default/cheats/Prompt.t.sol | 23 +- testdata/default/cheats/RandomAddress.t.sol | 7 +- testdata/default/cheats/RandomBytes.t.sol | 7 +- .../default/cheats/RandomCheatcodes.t.sol | 11 +- testdata/default/cheats/RandomUint.t.sol | 7 +- testdata/default/cheats/ReadCallers.t.sol | 7 +- testdata/default/cheats/Record.t.sol | 7 +- .../cheats/RecordAccountAccesses.t.sol | 108 +- .../default/cheats/RecordDebugTrace.t.sol | 19 +- testdata/default/cheats/RecordLogs.t.sol | 6 +- testdata/default/cheats/Remember.t.sol | 7 +- testdata/default/cheats/ResetNonce.t.sol | 6 +- testdata/default/cheats/Rlp.t.sol | 7 +- testdata/default/cheats/Roll.t.sol | 7 +- testdata/default/cheats/RpcUrls.t.sol | 7 +- testdata/default/cheats/Seed.t.sol | 7 +- testdata/default/cheats/SetBlockhash.t.sol | 7 +- testdata/default/cheats/SetNonce.t.sol | 6 +- testdata/default/cheats/SetNonceUnsafe.t.sol | 6 +- testdata/default/cheats/Setup.t.sol | 6 +- testdata/default/cheats/Shuffle.t.sol | 7 +- testdata/default/cheats/Sign.t.sol | 7 +- testdata/default/cheats/SignP256.t.sol | 7 +- testdata/default/cheats/Skip.t.sol | 7 +- testdata/default/cheats/Sleep.t.sol | 7 +- testdata/default/cheats/Sort.t.sol | 7 +- .../default/cheats/StateDiffBytesString.t.sol | 6 +- .../default/cheats/StateDiffMappings.t.sol | 6 +- .../cheats/StateDiffStorageLayout.t.sol | 6 +- .../default/cheats/StateDiffStructTest.t.sol | 6 +- testdata/default/cheats/StateSnapshots.t.sol | 11 +- .../default/cheats/StorageSlotState.t.sol | 7 +- testdata/default/cheats/Store.t.sol | 6 +- testdata/default/cheats/StringUtils.t.sol | 7 +- testdata/default/cheats/ToString.t.sol | 7 +- testdata/default/cheats/Toml.t.sol | 11 +- testdata/default/cheats/Travel.t.sol | 7 +- testdata/default/cheats/TryFfi.sol | 7 +- testdata/default/cheats/UnixTime.t.sol | 7 +- testdata/default/cheats/Wallet.t.sol | 7 +- testdata/default/cheats/Warp.t.sol | 19 +- testdata/default/cheats/dumpState.t.sol | 7 +- testdata/default/cheats/getBlockNumber.t.sol | 7 +- testdata/default/cheats/loadAllocs.t.sol | 6 +- .../default/core/BadSigAfterInvariant.t.sol | 4 +- .../default/core/ContractEnvironment.t.sol | 4 +- .../core/FailingTestAfterFailedSetup.t.sol | 18 - testdata/default/core/LegacyAssertions.t.sol | 24 - testdata/default/core/PaymentFailure.t.sol | 19 - testdata/default/core/Reverting.t.sol | 7 +- testdata/default/core/SetupConsistency.t.sol | 4 +- testdata/default/fork/ForkSame_1.t.sol | 6 +- testdata/default/fork/ForkSame_2.t.sol | 6 +- testdata/default/fork/LaunchFork.t.sol | 21 +- testdata/default/fs/Disabled.t.sol | 23 +- .../fs/{Default.t.sol => ReadOnly.sol} | 14 +- testdata/default/fuzz/Fuzz.t.sol | 31 - testdata/default/fuzz/FuzzCollection.t.sol | 70 - .../default/fuzz/FuzzFailurePersist.t.sol | 29 - testdata/default/fuzz/FuzzInt.t.sol | 58 - testdata/default/fuzz/FuzzPositive.t.sol | 18 - testdata/default/fuzz/FuzzUint.t.sol | 46 - .../common/InvariantAfterInvariant.t.sol | 55 - .../invariant/common/InvariantAssume.t.sol | 23 - .../common/InvariantCalldataDictionary.t.sol | 95 -- .../common/InvariantCustomError.t.sol | 35 - .../common/InvariantExcludedSenders.t.sol | 22 - .../invariant/common/InvariantFixtures.t.sol | 77 - .../common/InvariantHandlerFailure.t.sol | 35 - .../common/InvariantInnerContract.t.sol | 50 - .../common/InvariantPreserveState.t.sol | 49 - .../common/InvariantReentrancy.t.sol | 55 - .../invariant/common/InvariantRollFork.t.sol | 50 - .../common/InvariantScrapeValues.t.sol | 69 - .../common/InvariantSequenceNoReverts.t.sol | 25 - .../common/InvariantShrinkBigSequence.t.sol | 31 - .../common/InvariantShrinkFailOnRevert.t.sol | 26 - .../common/InvariantShrinkWithAssert.t.sol | 32 - .../invariant/common/InvariantTest1.t.sol | 39 - .../invariant/target/ExcludeContracts.t.sol | 31 - .../invariant/target/ExcludeSelectors.t.sol | 41 - .../invariant/target/ExcludeSenders.t.sol | 45 - .../target/FuzzedTargetContracts.t.sol | 66 - .../invariant/target/TargetContracts.t.sol | 32 - .../invariant/target/TargetInterfaces.t.sol | 72 - .../invariant/target/TargetSelectors.t.sol | 41 - .../fuzz/invariant/target/TargetSenders.t.sol | 31 - .../targetAbi/ExcludeArtifacts.t.sol | 45 - .../targetAbi/TargetArtifactSelectors.t.sol | 42 - .../targetAbi/TargetArtifactSelectors2.t.sol | 72 - .../invariant/targetAbi/TargetArtifacts.t.sol | 44 - testdata/default/inline/FuzzInlineConf.t.sol | 6 +- .../default/inline/InvariantInlineConf.t.sol | 6 +- .../default/linking/duplicate/Duplicate.t.sol | 4 +- testdata/default/linking/nested/Nested.t.sol | 4 +- testdata/default/linking/simple/Simple.t.sol | 4 +- testdata/default/logs/DebugLogs.t.sol | 105 -- testdata/default/logs/HardhatLogs.t.sol | 238 --- testdata/default/repros/Issue10302.t.sol | 7 +- testdata/default/repros/Issue10477.t.sol | 7 +- testdata/default/repros/Issue10527.t.sol | 7 +- testdata/default/repros/Issue10552.t.sol | 7 +- testdata/default/repros/Issue10586.t.sol | 11 +- testdata/default/repros/Issue10957.t.sol | 7 +- testdata/default/repros/Issue11353.t.sol | 7 +- testdata/default/repros/Issue11616.t.sol | 6 +- testdata/default/repros/Issue2623.t.sol | 7 +- testdata/default/repros/Issue2629.t.sol | 7 +- testdata/default/repros/Issue2723.t.sol | 7 +- testdata/default/repros/Issue2851.t.sol | 29 - testdata/default/repros/Issue2898.t.sol | 7 +- testdata/default/repros/Issue2956.t.sol | 6 +- testdata/default/repros/Issue2984.t.sol | 6 +- testdata/default/repros/Issue3055.t.sol | 36 - testdata/default/repros/Issue3077.t.sol | 7 +- testdata/default/repros/Issue3110.t.sol | 7 +- testdata/default/repros/Issue3119.t.sol | 7 +- testdata/default/repros/Issue3189.t.sol | 32 - testdata/default/repros/Issue3190.t.sol | 8 +- testdata/default/repros/Issue3192.t.sol | 6 +- testdata/default/repros/Issue3220.t.sol | 6 +- testdata/default/repros/Issue3221.t.sol | 6 +- testdata/default/repros/Issue3223.t.sol | 7 +- testdata/default/repros/Issue3347.t.sol | 14 - testdata/default/repros/Issue3596.t.sol | 31 - testdata/default/repros/Issue3653.t.sol | 6 +- testdata/default/repros/Issue3661.t.sol | 4 +- testdata/default/repros/Issue3674.t.sol | 10 +- testdata/default/repros/Issue3685.t.sol | 7 +- testdata/default/repros/Issue3703.t.sol | 9 +- testdata/default/repros/Issue3708.t.sol | 6 +- testdata/default/repros/Issue3753.t.sol | 7 +- testdata/default/repros/Issue3792.t.sol | 4 +- testdata/default/repros/Issue4232.t.sol | 7 +- testdata/default/repros/Issue4402.t.sol | 7 +- testdata/default/repros/Issue4586.t.sol | 10 +- testdata/default/repros/Issue4630.t.sol | 7 +- testdata/default/repros/Issue4640.t.sol | 7 +- testdata/default/repros/Issue5038.t.sol | 7 +- testdata/default/repros/Issue5529.t.sol | 16 +- testdata/default/repros/Issue5739.t.sol | 6 +- testdata/default/repros/Issue5808.t.sol | 7 +- testdata/default/repros/Issue5929.t.sol | 7 +- testdata/default/repros/Issue5935.t.sol | 7 +- testdata/default/repros/Issue5948.t.sol | 7 +- testdata/default/repros/Issue6006.t.sol | 7 +- testdata/default/repros/Issue6032.t.sol | 7 +- testdata/default/repros/Issue6070.t.sol | 7 +- testdata/default/repros/Issue6115.t.sol | 4 +- testdata/default/repros/Issue6170.t.sol | 28 - testdata/default/repros/Issue6180.t.sol | 7 +- testdata/default/repros/Issue6293.t.sol | 7 +- testdata/default/repros/Issue6355.t.sol | 39 - testdata/default/repros/Issue6437.t.sol | 7 +- testdata/default/repros/Issue6501.t.sol | 14 - testdata/default/repros/Issue6538.t.sol | 7 +- testdata/default/repros/Issue6554.t.sol | 11 +- testdata/default/repros/Issue6616.t.sol | 7 +- testdata/default/repros/Issue6634.t.sol | 9 +- testdata/default/repros/Issue6643.t.sol | 6 +- testdata/default/repros/Issue6759.t.sol | 7 +- testdata/default/repros/Issue6966.t.sol | 4 +- testdata/default/repros/Issue7238.t.sol | 7 +- testdata/default/repros/Issue7457.t.sol | 7 +- testdata/default/repros/Issue7481.t.sol | 7 +- testdata/default/repros/Issue8004.t.sol | 12 +- testdata/default/repros/Issue8006.t.sol | 6 +- testdata/default/repros/Issue8168.t.sol | 7 +- testdata/default/repros/Issue8277.t.sol | 7 +- testdata/default/repros/Issue8287.t.sol | 7 +- testdata/default/repros/Issue8566.t.sol | 7 +- testdata/default/repros/Issue8639.t.sol | 10 +- testdata/default/repros/Issue8971.t.sol | 6 +- testdata/default/repros/Issue9643.t.sol | 9 +- testdata/default/spec/ShanghaiCompat.t.sol | 7 +- .../default/trace/ConflictingSignatures.t.sol | 41 - testdata/default/trace/Trace.t.sol | 98 -- testdata/default/vyper/CounterTest.vy | 4 +- testdata/fixtures/File/ignored/.gitignore | 1 + testdata/foundry.toml | 56 +- testdata/multi-version/Counter.sol | 2 + testdata/multi-version/cheats/GetCode.t.sol | 7 +- testdata/multi-version/cheats/GetCode17.t.sol | 7 +- testdata/paris/cheats/Fork.t.sol | 6 +- testdata/paris/cheats/GasSnapshots.t.sol | 23 +- testdata/paris/cheats/LastCallGas.t.sol | 7 +- testdata/paris/core/BeforeTest.t.sol | 22 +- testdata/paris/fork/Transact.t.sol | 8 +- testdata/paris/spec/ShanghaiCompat.t.sol | 7 +- testdata/{default/vyper => src}/Counter.vy | 0 testdata/{default/vyper => src}/ICounter.vyi | 0 .../ds-test/src/test.sol => utils/DSTest.sol} | 0 testdata/utils/Test.sol | 11 + testdata/{cheats => utils}/Vm.sol | 0 testdata/{default/logs => utils}/console.sol | 0 286 files changed, 5645 insertions(+), 6884 deletions(-) create mode 100644 crates/forge/tests/cli/test_cmd/core.rs create mode 100644 crates/forge/tests/cli/test_cmd/fuzz.rs create mode 100644 crates/forge/tests/cli/test_cmd/invariant/common.rs rename crates/forge/tests/{it/invariant.rs => cli/test_cmd/invariant/mod.rs} (54%) rename testdata/default/fuzz/invariant/storage/InvariantStorageTest.t.sol => crates/forge/tests/cli/test_cmd/invariant/storage.rs (79%) create mode 100644 crates/forge/tests/cli/test_cmd/invariant/target.rs create mode 100644 crates/forge/tests/cli/test_cmd/logs.rs rename crates/forge/tests/cli/{test_cmd.rs => test_cmd/mod.rs} (98%) rename testdata/default/repros/Issue8383.t.sol => crates/forge/tests/cli/test_cmd/repros.rs (57%) rename crates/forge/tests/{it => cli/test_cmd}/spec.rs (93%) rename crates/forge/tests/{it => cli/test_cmd}/table.rs (100%) create mode 100644 crates/forge/tests/cli/test_cmd/trace.rs delete mode 100644 crates/forge/tests/it/cheats.rs delete mode 100644 crates/forge/tests/it/config.rs delete mode 100644 crates/forge/tests/it/core.rs delete mode 100644 crates/forge/tests/it/fork.rs delete mode 100644 crates/forge/tests/it/fs.rs delete mode 100644 crates/forge/tests/it/fuzz.rs delete mode 100644 crates/forge/tests/it/inline.rs delete mode 100644 crates/forge/tests/it/main.rs delete mode 100644 crates/forge/tests/it/repros.rs delete mode 100644 crates/forge/tests/it/test_helpers.rs delete mode 100644 crates/forge/tests/it/vyper.rs delete mode 100644 testdata/default/core/FailingTestAfterFailedSetup.t.sol delete mode 100644 testdata/default/core/LegacyAssertions.t.sol delete mode 100644 testdata/default/core/PaymentFailure.t.sol rename testdata/default/fs/{Default.t.sol => ReadOnly.sol} (68%) delete mode 100644 testdata/default/fuzz/Fuzz.t.sol delete mode 100644 testdata/default/fuzz/FuzzCollection.t.sol delete mode 100644 testdata/default/fuzz/FuzzFailurePersist.t.sol delete mode 100644 testdata/default/fuzz/FuzzInt.t.sol delete mode 100644 testdata/default/fuzz/FuzzPositive.t.sol delete mode 100644 testdata/default/fuzz/FuzzUint.t.sol delete mode 100644 testdata/default/fuzz/invariant/common/InvariantAfterInvariant.t.sol delete mode 100644 testdata/default/fuzz/invariant/common/InvariantAssume.t.sol delete mode 100644 testdata/default/fuzz/invariant/common/InvariantCalldataDictionary.t.sol delete mode 100644 testdata/default/fuzz/invariant/common/InvariantCustomError.t.sol delete mode 100644 testdata/default/fuzz/invariant/common/InvariantExcludedSenders.t.sol delete mode 100644 testdata/default/fuzz/invariant/common/InvariantFixtures.t.sol delete mode 100644 testdata/default/fuzz/invariant/common/InvariantHandlerFailure.t.sol delete mode 100644 testdata/default/fuzz/invariant/common/InvariantInnerContract.t.sol delete mode 100644 testdata/default/fuzz/invariant/common/InvariantPreserveState.t.sol delete mode 100644 testdata/default/fuzz/invariant/common/InvariantReentrancy.t.sol delete mode 100644 testdata/default/fuzz/invariant/common/InvariantRollFork.t.sol delete mode 100644 testdata/default/fuzz/invariant/common/InvariantScrapeValues.t.sol delete mode 100644 testdata/default/fuzz/invariant/common/InvariantSequenceNoReverts.t.sol delete mode 100644 testdata/default/fuzz/invariant/common/InvariantShrinkBigSequence.t.sol delete mode 100644 testdata/default/fuzz/invariant/common/InvariantShrinkFailOnRevert.t.sol delete mode 100644 testdata/default/fuzz/invariant/common/InvariantShrinkWithAssert.t.sol delete mode 100644 testdata/default/fuzz/invariant/common/InvariantTest1.t.sol delete mode 100644 testdata/default/fuzz/invariant/target/ExcludeContracts.t.sol delete mode 100644 testdata/default/fuzz/invariant/target/ExcludeSelectors.t.sol delete mode 100644 testdata/default/fuzz/invariant/target/ExcludeSenders.t.sol delete mode 100644 testdata/default/fuzz/invariant/target/FuzzedTargetContracts.t.sol delete mode 100644 testdata/default/fuzz/invariant/target/TargetContracts.t.sol delete mode 100644 testdata/default/fuzz/invariant/target/TargetInterfaces.t.sol delete mode 100644 testdata/default/fuzz/invariant/target/TargetSelectors.t.sol delete mode 100644 testdata/default/fuzz/invariant/target/TargetSenders.t.sol delete mode 100644 testdata/default/fuzz/invariant/targetAbi/ExcludeArtifacts.t.sol delete mode 100644 testdata/default/fuzz/invariant/targetAbi/TargetArtifactSelectors.t.sol delete mode 100644 testdata/default/fuzz/invariant/targetAbi/TargetArtifactSelectors2.t.sol delete mode 100644 testdata/default/fuzz/invariant/targetAbi/TargetArtifacts.t.sol delete mode 100644 testdata/default/logs/DebugLogs.t.sol delete mode 100644 testdata/default/logs/HardhatLogs.t.sol delete mode 100644 testdata/default/repros/Issue2851.t.sol delete mode 100644 testdata/default/repros/Issue3055.t.sol delete mode 100644 testdata/default/repros/Issue3189.t.sol delete mode 100644 testdata/default/repros/Issue3347.t.sol delete mode 100644 testdata/default/repros/Issue3596.t.sol delete mode 100644 testdata/default/repros/Issue6170.t.sol delete mode 100644 testdata/default/repros/Issue6355.t.sol delete mode 100644 testdata/default/repros/Issue6501.t.sol delete mode 100644 testdata/default/trace/ConflictingSignatures.t.sol delete mode 100644 testdata/default/trace/Trace.t.sol create mode 100644 testdata/fixtures/File/ignored/.gitignore rename testdata/{default/vyper => src}/Counter.vy (100%) rename testdata/{default/vyper => src}/ICounter.vyi (100%) rename testdata/{lib/ds-test/src/test.sol => utils/DSTest.sol} (100%) create mode 100644 testdata/utils/Test.sol rename testdata/{cheats => utils}/Vm.sol (100%) rename testdata/{default/logs => utils}/console.sol (100%) diff --git a/.github/workflows/nextest.yml b/.github/workflows/nextest.yml index 3d7ef42941deb..272e1c7fcb8b4 100644 --- a/.github/workflows/nextest.yml +++ b/.github/workflows/nextest.yml @@ -98,7 +98,10 @@ jobs: ~/.config/.foundry/cache testdata/cache testdata/out - key: ${{ runner.os }}-foundry-${{ matrix.name }} + # Use a unique key for each run to always update the cache. + key: foundry-${{ matrix.name }}-${{ github.run_id }} + restore-keys: | + foundry-${{ matrix.name }}- - uses: mozilla-actions/sccache-action@7d986dd989559c6ecdb630a3fd2557667be217ad # v0.0.9 - name: Setup Git config run: | diff --git a/Cargo.lock b/Cargo.lock index 61d92544e9846..b6f44ac1c26a2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -70,9 +70,9 @@ dependencies = [ [[package]] name = "alloy-consensus" -version = "1.0.38" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a0dd3ed764953a6b20458b2b7abbfdc93d20d14b38babe1a70fe631a443a9f1" +checksum = "b9b151e38e42f1586a01369ec52a6934702731d07e8509a7307331b09f6c46dc" dependencies = [ "alloy-eips", "alloy-primitives", @@ -96,9 +96,9 @@ dependencies = [ [[package]] name = "alloy-consensus-any" -version = "1.0.38" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9556182afa73cddffa91e64a5aa9508d5e8c912b3a15f26998d2388a824d2c7b" +checksum = "6e2d5e8668ef6215efdb7dcca6f22277b4e483a5650e05f5de22b2350971f4b8" dependencies = [ "alloy-consensus", "alloy-eips", @@ -110,9 +110,9 @@ dependencies = [ [[package]] name = "alloy-contract" -version = "1.0.38" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b19d7092c96defc3d132ee0d8969ca1b79ef512b5eda5c66e3065266b253adf2" +checksum = "630288cf4f3a34a8c6bc75c03dce1dbd47833138f65f37d53a1661eafc96b83f" dependencies = [ "alloy-consensus", "alloy-dyn-abi", @@ -176,9 +176,9 @@ dependencies = [ [[package]] name = "alloy-eip5792" -version = "1.0.38" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e21b782483672d41c62e27973102276060f9526badf3a260adea8cdf4adc049e" +checksum = "15a5ec61206c5b2113bd79b0690395a456ef542d63b596c661b6aaf402f4a34d" dependencies = [ "alloy-primitives", "alloy-serde", @@ -201,9 +201,9 @@ dependencies = [ [[package]] name = "alloy-eips" -version = "1.0.38" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "305fa99b538ca7006b0c03cfed24ec6d82beda67aac857ef4714be24231d15e6" +checksum = "e5434834adaf64fa20a6fb90877bc1d33214c41b055cc49f82189c98614368cc" dependencies = [ "alloy-eip2124", "alloy-eip2930", @@ -225,9 +225,9 @@ dependencies = [ [[package]] name = "alloy-ens" -version = "1.0.38" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a00efb95ebca2feb59b53930b295f853aef4e0642e865610f3d824d2727ca74" +checksum = "23e7b71e8963a7920dff8c1d4380ea275b3b37c5abde1fc8ea501cd2bffb159b" dependencies = [ "alloy-contract", "alloy-primitives", @@ -262,9 +262,9 @@ dependencies = [ [[package]] name = "alloy-genesis" -version = "1.0.38" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a272533715aefc900f89d51db00c96e6fd4f517ea081a12fea482a352c8c815c" +checksum = "919a8471cfbed7bcd8cf1197a57dda583ce0e10c6385f6ff4e8b41304b223392" dependencies = [ "alloy-eips", "alloy-primitives", @@ -300,9 +300,9 @@ dependencies = [ [[package]] name = "alloy-json-rpc" -version = "1.0.38" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d91676d242c0ced99c0dd6d0096d7337babe9457cc43407d26aa6367fcf90553" +checksum = "d7c69f6c9c68a1287c9d5ff903d0010726934de0dac10989be37b75a29190d55" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -315,9 +315,9 @@ dependencies = [ [[package]] name = "alloy-network" -version = "1.0.38" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77f82150116b30ba92f588b87f08fa97a46a1bd5ffc0d0597efdf0843d36bfda" +checksum = "8eaf2ae05219e73e0979cb2cf55612aafbab191d130f203079805eaf881cca58" dependencies = [ "alloy-consensus", "alloy-consensus-any", @@ -341,9 +341,9 @@ dependencies = [ [[package]] name = "alloy-network-primitives" -version = "1.0.38" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "223612259a080160ce839a4e5df0125ca403a1d5e7206cc911cea54af5d769aa" +checksum = "e58f4f345cef483eab7374f2b6056973c7419ffe8ad35e994b7a7f5d8e0c7ba4" dependencies = [ "alloy-consensus", "alloy-eips", @@ -413,9 +413,9 @@ dependencies = [ [[package]] name = "alloy-provider" -version = "1.0.38" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7283b81b6f136100b152e699171bc7ed8184a58802accbc91a7df4ebb944445" +checksum = "de2597751539b1cc8fe4204e5325f9a9ed83fcacfb212018dfcfa7877e76de21" dependencies = [ "alloy-chains", "alloy-consensus", @@ -458,9 +458,9 @@ dependencies = [ [[package]] name = "alloy-pubsub" -version = "1.0.38" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eee7e3d343814ec0dfea69bd1820042a133a9d0b9ac5faf1e6eb133b43366315" +checksum = "06e45a68423e732900a0c824b8e22237db461b79d2e472dd68b7547c16104427" dependencies = [ "alloy-json-rpc", "alloy-primitives", @@ -502,9 +502,9 @@ dependencies = [ [[package]] name = "alloy-rpc-client" -version = "1.0.38" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1154b12d470bef59951c62676e106f4ce5de73b987d86b9faa935acebb138ded" +checksum = "edf8eb8be597cfa8c312934d2566ec4516f066d69164f9212d7a148979fdcfd8" dependencies = [ "alloy-json-rpc", "alloy-primitives", @@ -528,9 +528,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types" -version = "1.0.38" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47ab76bf97648a1c6ad8fb00f0d594618942b5a9e008afbfb5c8a8fca800d574" +checksum = "339af7336571dd39ae3a15bde08ae6a647e62f75350bd415832640268af92c06" dependencies = [ "alloy-primitives", "alloy-rpc-types-anvil", @@ -544,9 +544,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-anvil" -version = "1.0.38" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "456cfc2c1677260edbd7ce3eddb7de419cb46de0e9826c43401f42b0286a779a" +checksum = "83d98fb386a462e143f5efa64350860af39950c49e7c0cbdba419c16793116ef" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", @@ -556,9 +556,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-any" -version = "1.0.38" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23cc57ee0c1ac9fb14854195fc249494da7416591dc4a4d981ddfd5dd93b9bce" +checksum = "fbde0801a32d21c5f111f037bee7e22874836fba7add34ed4a6919932dd7cf23" dependencies = [ "alloy-consensus-any", "alloy-rpc-types-eth", @@ -567,9 +567,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-beacon" -version = "1.0.38" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfa4edd92c3124ec19b9d572dc7923d070fe5c2efb677519214affd6156a4463" +checksum = "55c8d51ebb7c5fa8be8ea739a3933c5bfea08777d2d662b30b2109ac5ca71e6b" dependencies = [ "alloy-eips", "alloy-primitives", @@ -583,9 +583,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-debug" -version = "1.0.38" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a0ac29dd005c33e3f7e09087accc80843315303685c3f7a1b888002cd27785b" +checksum = "388cf910e66bd4f309a81ef746dcf8f9bca2226e3577890a8d56c5839225cf46" dependencies = [ "alloy-primitives", "derive_more", @@ -595,9 +595,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-engine" -version = "1.0.38" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d9d173854879bcf26c7d71c1c3911972a3314df526f4349ffe488e676af577d" +checksum = "605ec375d91073851f566a3082548af69a28dca831b27a8be7c1b4c49f5c6ca2" dependencies = [ "alloy-consensus", "alloy-eips", @@ -615,9 +615,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-eth" -version = "1.0.38" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d7d47bca1a2a1541e4404aa38b7e262bb4dffd9ac23b4f178729a4ddc5a5caa" +checksum = "361cd87ead4ba7659bda8127902eda92d17fa7ceb18aba1676f7be10f7222487" dependencies = [ "alloy-consensus", "alloy-consensus-any", @@ -636,9 +636,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-trace" -version = "1.0.38" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c331c8e48665607682e8a9549a2347c13674d4fbcbdc342e7032834eba2424f4" +checksum = "de4e95fb0572b97b17751d0fdf5cdc42b0050f9dd9459eddd1bf2e2fbfed0a33" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", @@ -650,9 +650,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-txpool" -version = "1.0.38" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e2f66afe1e76ca4485e593980056f061b2bdae2055486a062fca050ff111a52" +checksum = "cddde1bbd4feeb0d363ae7882af1e2e7955ef77c17f933f31402aad9343b57c5" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", @@ -662,9 +662,9 @@ dependencies = [ [[package]] name = "alloy-serde" -version = "1.0.38" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8468f1a7f9ee3bae73c24eead0239abea720dbf7779384b9c7e20d51bfb6b0" +checksum = "64600fc6c312b7e0ba76f73a381059af044f4f21f43e07f51f1fa76c868fe302" dependencies = [ "alloy-primitives", "serde", @@ -673,9 +673,9 @@ dependencies = [ [[package]] name = "alloy-signer" -version = "1.0.38" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33387c90b0a5021f45a5a77c2ce6c49b8f6980e66a318181468fb24cea771670" +checksum = "5772858492b26f780468ae693405f895d6a27dea6e3eab2c36b6217de47c2647" dependencies = [ "alloy-dyn-abi", "alloy-primitives", @@ -690,9 +690,9 @@ dependencies = [ [[package]] name = "alloy-signer-aws" -version = "1.0.38" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83bf90f2355769ad93f790b930434b8d3d2948317f3e484de458010409024462" +checksum = "66acf5f8745dd935e94855aada39d83b555112872321d9293748424de144897e" dependencies = [ "alloy-consensus", "alloy-network", @@ -709,9 +709,9 @@ dependencies = [ [[package]] name = "alloy-signer-gcp" -version = "1.0.38" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2c768277bfc541a7aab3c3a079d838b3925b6c2f367e29be943f002ecde2712" +checksum = "0ccf849fbbdbd3657c0fd07e5654b8880f25bdcb325424edde5e1a4a77b48816" dependencies = [ "alloy-consensus", "alloy-network", @@ -727,9 +727,9 @@ dependencies = [ [[package]] name = "alloy-signer-ledger" -version = "1.0.38" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ccf703581d2c0b2dd2d5bd235de2b5ccfd6bdc43e750ac767327fe0fb0b4ea1" +checksum = "4599a95670313c028b1f69c425deee72c26f2c4911713eb49a4d5faf9eb67c29" dependencies = [ "alloy-consensus", "alloy-dyn-abi", @@ -747,9 +747,9 @@ dependencies = [ [[package]] name = "alloy-signer-local" -version = "1.0.38" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b55d9e795c85e36dcea08786d2e7ae9b73cb554b6bea6ac4c212def24e1b4d03" +checksum = "f4195b803d0a992d8dbaab2ca1986fc86533d4bc80967c0cce7668b26ad99ef9" dependencies = [ "alloy-consensus", "alloy-network", @@ -767,9 +767,9 @@ dependencies = [ [[package]] name = "alloy-signer-trezor" -version = "1.0.38" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "675184c6682378f32ce8fc8429f91e93f72098b8a73af6a9447549b6606241ea" +checksum = "f9985b3afacb904655814a47816cc3e1dc8819753b7896ee7bef7e8c66f8e697" dependencies = [ "alloy-consensus", "alloy-network", @@ -857,9 +857,9 @@ dependencies = [ [[package]] name = "alloy-transport" -version = "1.0.38" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702002659778d89a94cd4ff2044f6b505460df6c162e2f47d1857573845b0ace" +checksum = "025a940182bddaeb594c26fe3728525ae262d0806fe6a4befdf5d7bc13d54bce" dependencies = [ "alloy-json-rpc", "alloy-primitives", @@ -881,9 +881,9 @@ dependencies = [ [[package]] name = "alloy-transport-http" -version = "1.0.38" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d6bdc0830e5e8f08a4c70a4c791d400a86679c694a3b4b986caf26fad680438" +checksum = "e3b5064d1e1e1aabc918b5954e7fb8154c39e77ec6903a581b973198b26628fa" dependencies = [ "alloy-json-rpc", "alloy-transport", @@ -896,9 +896,9 @@ dependencies = [ [[package]] name = "alloy-transport-ipc" -version = "1.0.38" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ce41d99a32346f354725fe62eadd271cdbae45fe6b3cc40cb054e0bf763112" +checksum = "d47962f3f1d9276646485458dc842b4e35675f42111c9d814ae4711c664c8300" dependencies = [ "alloy-json-rpc", "alloy-pubsub", @@ -916,9 +916,9 @@ dependencies = [ [[package]] name = "alloy-transport-ws" -version = "1.0.38" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "686219dcef201655763bd3d4eabe42388d9368bfbf6f1c8016d14e739ec53aac" +checksum = "9476a36a34e2fb51b6746d009c53d309a186a825aa95435407f0e07149f4ad2d" dependencies = [ "alloy-pubsub", "alloy-transport", @@ -950,9 +950,9 @@ dependencies = [ [[package]] name = "alloy-tx-macros" -version = "1.0.38" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bf39928a5e70c9755d6811a2928131b53ba785ad37c8bf85c90175b5d43b818" +checksum = "f8e52276fdb553d3c11563afad2898f4085165e4093604afe3d78b69afbf408f" dependencies = [ "alloy-primitives", "darling 0.21.3", @@ -3573,7 +3573,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -3832,7 +3832,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -6731,7 +6731,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -8505,7 +8505,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.11.0", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -9742,7 +9742,7 @@ dependencies = [ "getrandom 0.3.3", "once_cell", "rustix 1.1.2", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -9762,7 +9762,7 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2111ef44dae28680ae9752bb89409e7310ca33a8c621ebe7b106cf5c928b3ac0" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -11035,7 +11035,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index bda08cf270a9d..269c294f25b83 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -236,30 +236,30 @@ svm = { package = "svm-rs", version = "0.5", default-features = false, features ] } ## alloy -alloy-consensus = { version = "1.0.38", default-features = false } -alloy-contract = { version = "1.0.38", default-features = false } -alloy-eips = { version = "1.0.38", default-features = false } -alloy-eip5792 = { version = "1.0.38", default-features = false } -alloy-ens = { version = "1.0.38", default-features = false } -alloy-genesis = { version = "1.0.38", default-features = false } -alloy-json-rpc = { version = "1.0.38", default-features = false } -alloy-network = { version = "1.0.38", default-features = false } -alloy-provider = { version = "1.0.38", default-features = false } -alloy-pubsub = { version = "1.0.38", default-features = false } -alloy-rpc-client = { version = "1.0.38", default-features = false } -alloy-rpc-types = { version = "1.0.38", default-features = true } -alloy-rpc-types-beacon = { version = "1.0.38", default-features = true } -alloy-serde = { version = "1.0.38", default-features = false } -alloy-signer = { version = "1.0.38", default-features = false } -alloy-signer-aws = { version = "1.0.38", default-features = false } -alloy-signer-gcp = { version = "1.0.38", default-features = false } -alloy-signer-ledger = { version = "1.0.38", default-features = false } -alloy-signer-local = { version = "1.0.38", default-features = false } -alloy-signer-trezor = { version = "1.0.38", default-features = false } -alloy-transport = { version = "1.0.38", default-features = false } -alloy-transport-http = { version = "1.0.38", default-features = false } -alloy-transport-ipc = { version = "1.0.38", default-features = false } -alloy-transport-ws = { version = "1.0.38", default-features = false } +alloy-consensus = { version = "1.0.41", default-features = false } +alloy-contract = { version = "1.0.41", default-features = false } +alloy-eips = { version = "1.0.41", default-features = false } +alloy-eip5792 = { version = "1.0.41", default-features = false } +alloy-ens = { version = "1.0.41", default-features = false } +alloy-genesis = { version = "1.0.41", default-features = false } +alloy-json-rpc = { version = "1.0.41", default-features = false } +alloy-network = { version = "1.0.41", default-features = false } +alloy-provider = { version = "1.0.41", default-features = false } +alloy-pubsub = { version = "1.0.41", default-features = false } +alloy-rpc-client = { version = "1.0.41", default-features = false } +alloy-rpc-types = { version = "1.0.41", default-features = true } +alloy-rpc-types-beacon = { version = "1.0.41", default-features = true } +alloy-serde = { version = "1.0.41", default-features = false } +alloy-signer = { version = "1.0.41", default-features = false } +alloy-signer-aws = { version = "1.0.41", default-features = false } +alloy-signer-gcp = { version = "1.0.41", default-features = false } +alloy-signer-ledger = { version = "1.0.41", default-features = false } +alloy-signer-local = { version = "1.0.41", default-features = false } +alloy-signer-trezor = { version = "1.0.41", default-features = false } +alloy-transport = { version = "1.0.41", default-features = false } +alloy-transport-http = { version = "1.0.41", default-features = false } +alloy-transport-ipc = { version = "1.0.41", default-features = false } +alloy-transport-ws = { version = "1.0.41", default-features = false } alloy-hardforks = { version = "0.3.2", default-features = false } alloy-op-hardforks = { version = "0.3.2", default-features = false } diff --git a/crates/anvil/src/eth/backend/mem/mod.rs b/crates/anvil/src/eth/backend/mem/mod.rs index 64ca56809e0d5..72e3724ce1d5e 100644 --- a/crates/anvil/src/eth/backend/mem/mod.rs +++ b/crates/anvil/src/eth/backend/mem/mod.rs @@ -1520,7 +1520,7 @@ impl Backend { /// - `disable_eip3607` is set to `true` /// - `disable_base_fee` is set to `true` /// - `tx_gas_limit_cap` is set to `Some(u64::MAX)` indicating no gas limit cap - /// - `nonce` check is skipped if `request.nonce` is None + /// - `nonce` check is skipped fn build_call_env( &self, request: WithOtherFields, @@ -1571,6 +1571,9 @@ impl Backend { // - tracing env.evm_env.cfg_env.disable_base_fee = true; + // Disable nonce check in revm + env.evm_env.cfg_env.disable_nonce_check = true; + let gas_price = gas_price.or(max_fee_per_gas).unwrap_or_else(|| { self.fees().raw_gas_price().saturating_add(MIN_SUGGESTED_PRIORITY_FEE) }); @@ -1608,9 +1611,6 @@ impl Backend { if let Some(nonce) = nonce { env.tx.base.nonce = nonce; - } else { - // Disable nonce check in revm - env.evm_env.cfg_env.disable_nonce_check = true; } if env.evm_env.block_env.basefee == 0 { @@ -1909,8 +1909,9 @@ impl Backend { block_request: Option, opts: GethDebugTracingCallOptions, ) -> Result { - let GethDebugTracingCallOptions { tracing_options, block_overrides, state_overrides } = - opts; + let GethDebugTracingCallOptions { + tracing_options, block_overrides, state_overrides, .. + } = opts; let GethDebugTracingOptions { config, tracer, tracer_config, .. } = tracing_options; self.with_database_at(block_request, |state, mut block| { diff --git a/crates/cheatcodes/spec/src/lib.rs b/crates/cheatcodes/spec/src/lib.rs index 5ee5c03dea2b6..29e968aeb5bc6 100644 --- a/crates/cheatcodes/spec/src/lib.rs +++ b/crates/cheatcodes/spec/src/lib.rs @@ -117,8 +117,7 @@ mod tests { #[cfg(feature = "schema")] const SCHEMA_PATH: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/../assets/cheatcodes.schema.json"); - const IFACE_PATH: &str = - concat!(env!("CARGO_MANIFEST_DIR"), "/../../../testdata/cheats/Vm.sol"); + const IFACE_PATH: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/../../../testdata/utils/Vm.sol"); /// Generates the `cheatcodes.json` file contents. fn json_cheatcodes() -> String { diff --git a/crates/chisel/src/source.rs b/crates/chisel/src/source.rs index 8fce772a4ef69..576f36eab02f3 100644 --- a/crates/chisel/src/source.rs +++ b/crates/chisel/src/source.rs @@ -26,7 +26,7 @@ use walkdir::WalkDir; pub const MIN_VM_VERSION: Version = Version::new(0, 6, 2); /// Solidity source for the `Vm` interface in [forge-std](https://github.com/foundry-rs/forge-std) -static VM_SOURCE: &str = include_str!("../../../testdata/cheats/Vm.sol"); +static VM_SOURCE: &str = include_str!("../../../testdata/utils/Vm.sol"); /// [`SessionSource`] build output. pub struct GeneratedOutput { diff --git a/crates/common/src/fs.rs b/crates/common/src/fs.rs index 090f885e708a3..4cf3358f24400 100644 --- a/crates/common/src/fs.rs +++ b/crates/common/src/fs.rs @@ -5,7 +5,7 @@ use flate2::{Compression, read::GzDecoder, write::GzEncoder}; use serde::{Serialize, de::DeserializeOwned}; use std::{ fs::{self, File}, - io::{BufReader, BufWriter, Read, Write}, + io::{BufReader, BufWriter, Read, Seek, SeekFrom, Write}, path::{Component, Path, PathBuf}, }; @@ -62,25 +62,29 @@ pub fn read_json_gzip_file(path: &Path) -> Result { /// Reads the entire contents of a locked shared file into a string. pub fn locked_read_to_string(path: impl AsRef) -> Result { let path = path.as_ref(); - let file = + let mut file = fs::OpenOptions::new().read(true).open(path).map_err(|err| FsPathError::open(err, path))?; file.lock_shared().map_err(|err| FsPathError::lock(err, path))?; - let mut contents = String::new(); - (&file).read_to_string(&mut contents).map_err(|err| FsPathError::read(err, path))?; + let contents = read_inner(path, &mut file)?; file.unlock().map_err(|err| FsPathError::unlock(err, path))?; - Ok(contents) + String::from_utf8(contents).map_err(|err| FsPathError::read(std::io::Error::other(err), path)) } /// Reads the entire contents of a locked shared file into a bytes vector. pub fn locked_read(path: impl AsRef) -> Result> { let path = path.as_ref(); - let file = + let mut file = fs::OpenOptions::new().read(true).open(path).map_err(|err| FsPathError::open(err, path))?; file.lock_shared().map_err(|err| FsPathError::lock(err, path))?; + let contents = read_inner(path, &mut file)?; + file.unlock().map_err(|err| FsPathError::unlock(err, path))?; + Ok(contents) +} + +fn read_inner(path: &Path, file: &mut File) -> Result> { let file_len = file.metadata().map_err(|err| FsPathError::open(err, path))?.len() as usize; let mut buffer = Vec::with_capacity(file_len); - (&file).read_to_end(&mut buffer).map_err(|err| FsPathError::read(err, path))?; - file.unlock().map_err(|err| FsPathError::unlock(err, path))?; + file.read_to_end(&mut buffer).map_err(|err| FsPathError::read(err, path))?; Ok(buffer) } @@ -136,18 +140,39 @@ pub fn locked_write(path: impl AsRef, contents: impl AsRef<[u8]>) -> Resul } /// Writes a line in an exclusive locked file. -pub fn locked_write_line(path: impl AsRef, line: &String) -> Result<()> { +pub fn locked_write_line(path: impl AsRef, line: &str) -> Result<()> { let path = path.as_ref(); + if cfg!(windows) { + return locked_write_line_windows(path, line); + } + let mut file = std::fs::OpenOptions::new() .append(true) .create(true) .open(path) .map_err(|err| FsPathError::open(err, path))?; + file.lock().map_err(|err| FsPathError::lock(err, path))?; writeln!(file, "{line}").map_err(|err| FsPathError::write(err, path))?; file.unlock().map_err(|err| FsPathError::unlock(err, path)) } +// Locking fails on Windows if the file is opened in append mode. +fn locked_write_line_windows(path: &Path, line: &str) -> Result<()> { + let mut file = std::fs::OpenOptions::new() + .write(true) + .truncate(false) + .create(true) + .open(path) + .map_err(|err| FsPathError::open(err, path))?; + file.lock().map_err(|err| FsPathError::lock(err, path))?; + + file.seek(SeekFrom::End(0)).map_err(|err| FsPathError::write(err, path))?; + writeln!(file, "{line}").map_err(|err| FsPathError::write(err, path))?; + + file.unlock().map_err(|err| FsPathError::unlock(err, path)) +} + /// Wrapper for `std::fs::copy` pub fn copy(from: impl AsRef, to: impl AsRef) -> Result { let from = from.as_ref(); diff --git a/crates/forge/tests/cli/test_cmd/core.rs b/crates/forge/tests/cli/test_cmd/core.rs new file mode 100644 index 0000000000000..fffb6394e4779 --- /dev/null +++ b/crates/forge/tests/cli/test_cmd/core.rs @@ -0,0 +1,142 @@ +//! Core test functionality tests + +use foundry_test_utils::str; + +forgetest_init!(failing_test_after_failed_setup, |prj, cmd| { + prj.wipe_contracts(); + prj.add_test( + "FailingTestAfterFailedSetup.t.sol", + r#" +import "forge-std/Test.sol"; + +contract FailingTestAfterFailedSetupTest is Test { + function setUp() public { + assertTrue(false); + } + + function testAssertSuccess() public { + assertTrue(true); + } + + function testAssertFailure() public { + assertTrue(false); + } +} +"#, + ); + + cmd.arg("test").assert_failure().stdout_eq(str![[r#" +... +Ran 1 test for test/FailingTestAfterFailedSetup.t.sol:FailingTestAfterFailedSetupTest +[FAIL: assertion failed] setUp() ([GAS]) +Suite result: FAILED. 0 passed; 1 failed; 0 skipped; [ELAPSED] + +Ran 1 test suite [ELAPSED]: 0 tests passed, 1 failed, 0 skipped (1 total tests) + +Failing tests: +Encountered 1 failing test in test/FailingTestAfterFailedSetup.t.sol:FailingTestAfterFailedSetupTest +[FAIL: assertion failed] setUp() ([GAS]) + +Encountered a total of 1 failing tests, 0 tests succeeded + +Tip: Run `forge test --rerun` to retry only the 1 failed test + +"#]]); +}); + +forgetest_init!(legacy_assertions, |prj, cmd| { + prj.wipe_contracts(); + prj.add_test( + "LegacyAssertions.t.sol", + r#" +import "forge-std/Test.sol"; + +contract NoAssertionsRevertTest is Test { + function testMultipleAssertFailures() public { + vm.assertEq(uint256(1), uint256(2)); + vm.assertLt(uint256(5), uint256(4)); + } +} + +/// forge-config: default.legacy_assertions = true +contract LegacyAssertionsTest { + bool public failed; + + function testFlagNotSetSuccess() public {} + + function testFlagSetFailure() public { + failed = true; + } +} +"#, + ); + + cmd.args(["test", "-j1"]).assert_failure().stdout_eq(str![[r#" +... +Ran 2 tests for test/LegacyAssertions.t.sol:LegacyAssertionsTest +[PASS] testFlagNotSetSuccess() ([GAS]) +[FAIL] testFlagSetFailure() ([GAS]) +Suite result: FAILED. 1 passed; 1 failed; 0 skipped; [ELAPSED] + +Ran 1 test for test/LegacyAssertions.t.sol:NoAssertionsRevertTest +[FAIL: assertion failed: 1 != 2] testMultipleAssertFailures() ([GAS]) +Suite result: FAILED. 0 passed; 1 failed; 0 skipped; [ELAPSED] + +Ran 2 test suites [ELAPSED]: 1 tests passed, 2 failed, 0 skipped (3 total tests) + +Failing tests: +Encountered 1 failing test in test/LegacyAssertions.t.sol:LegacyAssertionsTest +[FAIL] testFlagSetFailure() ([GAS]) + +Encountered 1 failing test in test/LegacyAssertions.t.sol:NoAssertionsRevertTest +[FAIL: assertion failed: 1 != 2] testMultipleAssertFailures() ([GAS]) + +Encountered a total of 2 failing tests, 1 tests succeeded + +Tip: Run `forge test --rerun` to retry only the 2 failed tests + +"#]]); +}); + +forgetest_init!(payment_failure, |prj, cmd| { + prj.wipe_contracts(); + prj.add_test( + "PaymentFailure.t.sol", + r#" +import "forge-std/Test.sol"; + +contract Payable { + function pay() public payable {} +} + +contract PaymentFailureTest is Test { + function testCantPay() public { + Payable target = new Payable(); + vm.prank(address(1)); + target.pay{value: 1}(); + } +} +"#, + ); + + cmd.arg("test").assert_failure().stdout_eq(str![[r#" +[COMPILING_FILES] with [SOLC_VERSION] +[SOLC_VERSION] [ELAPSED] +Compiler run successful! + +Ran 1 test for test/PaymentFailure.t.sol:PaymentFailureTest +[FAIL: EvmError: Revert] testCantPay() ([GAS]) +Suite result: FAILED. 0 passed; 1 failed; 0 skipped; [ELAPSED] + +Ran 1 test suite [ELAPSED]: 0 tests passed, 1 failed, 0 skipped (1 total tests) + +Failing tests: +Encountered 1 failing test in test/PaymentFailure.t.sol:PaymentFailureTest +[FAIL: EvmError: Revert] testCantPay() ([GAS]) + +Encountered a total of 1 failing tests, 0 tests succeeded + +Tip: Run `forge test --rerun` to retry only the 1 failed test + +"#]]); +}); diff --git a/crates/forge/tests/cli/test_cmd/fuzz.rs b/crates/forge/tests/cli/test_cmd/fuzz.rs new file mode 100644 index 0000000000000..aaa8fe687d369 --- /dev/null +++ b/crates/forge/tests/cli/test_cmd/fuzz.rs @@ -0,0 +1,735 @@ +use alloy_primitives::U256; +use foundry_test_utils::{TestCommand, forgetest_init, str}; +use regex::Regex; + +forgetest_init!(test_can_scrape_bytecode, |prj, cmd| { + prj.update_config(|config| config.optimizer = Some(true)); + prj.add_source( + "FuzzerDict.sol", + r#" +// https://github.com/foundry-rs/foundry/issues/1168 +contract FuzzerDict { + // Immutables should get added to the dictionary. + address public immutable immutableOwner; + // Regular storage variables should also get added to the dictionary. + address public storageOwner; + + constructor(address _immutableOwner, address _storageOwner) { + immutableOwner = _immutableOwner; + storageOwner = _storageOwner; + } +} + "#, + ); + + prj.add_test( + "FuzzerDictTest.t.sol", + r#" +import {Test} from "forge-std/Test.sol"; +import "src/FuzzerDict.sol"; + +contract FuzzerDictTest is Test { + FuzzerDict fuzzerDict; + + function setUp() public { + fuzzerDict = new FuzzerDict(address(100), address(200)); + } + + /// forge-config: default.fuzz.runs = 2000 + function testImmutableOwner(address who) public { + assertTrue(who != fuzzerDict.immutableOwner()); + } + + /// forge-config: default.fuzz.runs = 2000 + function testStorageOwner(address who) public { + assertTrue(who != fuzzerDict.storageOwner()); + } +} + "#, + ); + + // Test that immutable address is used as fuzzed input, causing test to fail. + 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", "119", "--mt", "testStorageOwner"]) + .assert_failure(); +}); + +// tests that inline max-test-rejects config is properly applied +forgetest_init!(test_inline_max_test_rejects, |prj, cmd| { + prj.wipe_contracts(); + + prj.add_test( + "Contract.t.sol", + r#" +import {Test} from "forge-std/Test.sol"; + +contract InlineMaxRejectsTest is Test { + /// forge-config: default.fuzz.max-test-rejects = 1 + function test_fuzz_bound(uint256 a) public { + vm.assume(false); + } +} + "#, + ); + + cmd.args(["test"]).assert_failure().stdout_eq(str![[r#" +... +[FAIL: `vm.assume` rejected too many inputs (1 allowed)] test_fuzz_bound(uint256) (runs: 0, [AVG_GAS]) +... +"#]]); +}); + +// Tests that test timeout config is properly applied. +// If test doesn't timeout after one second, then test will fail with `rejected too many inputs`. +forgetest_init!(test_fuzz_timeout, |prj, cmd| { + prj.wipe_contracts(); + + prj.add_test( + "Contract.t.sol", + r#" +import {Test} from "forge-std/Test.sol"; + +contract FuzzTimeoutTest is Test { + /// forge-config: default.fuzz.max-test-rejects = 50000 + /// forge-config: default.fuzz.timeout = 1 + function test_fuzz_bound(uint256 a) public pure { + vm.assume(a == 0); + } +} + "#, + ); + + cmd.args(["test"]).assert_success().stdout_eq(str![[r#" +[COMPILING_FILES] with [SOLC_VERSION] +[SOLC_VERSION] [ELAPSED] +Compiler run successful! + +Ran 1 test for test/Contract.t.sol:FuzzTimeoutTest +[PASS] test_fuzz_bound(uint256) (runs: [..], [AVG_GAS]) +Suite result: ok. 1 passed; 0 failed; 0 skipped; [ELAPSED] + +Ran 1 test suite [ELAPSED]: 1 tests passed, 0 failed, 0 skipped (1 total tests) + +"#]]); +}); + +forgetest_init!(test_fuzz_fail_on_revert, |prj, cmd| { + prj.wipe_contracts(); + prj.update_config(|config| config.fuzz.fail_on_revert = false); + prj.add_source( + "Counter.sol", + r#" +contract Counter { + uint256 public number; + + function setNumber(uint256 newNumber) public { + require(number > 10000000000, "low number"); + number = newNumber; + } +} + "#, + ); + + prj.add_test( + "CounterTest.t.sol", + r#" +import {Test} from "forge-std/Test.sol"; +import "src/Counter.sol"; + +contract CounterTest is Test { + Counter public counter; + + function setUp() public { + counter = new Counter(); + } + + function testFuzz_SetNumberRequire(uint256 x) public { + counter.setNumber(x); + require(counter.number() == 1); + } + + function testFuzz_SetNumberAssert(uint256 x) public { + counter.setNumber(x); + assertEq(counter.number(), 1); + } +} + "#, + ); + + // Tests should not fail as revert happens in Counter contract. + cmd.args(["test", "--mc", "CounterTest"]).assert_success().stdout_eq(str![[r#" +[COMPILING_FILES] with [SOLC_VERSION] +[SOLC_VERSION] [ELAPSED] +Compiler run successful! + +Ran 2 tests for test/CounterTest.t.sol:CounterTest +[PASS] testFuzz_SetNumberAssert(uint256) (runs: 256, [AVG_GAS]) +[PASS] testFuzz_SetNumberRequire(uint256) (runs: 256, [AVG_GAS]) +Suite result: ok. 2 passed; 0 failed; 0 skipped; [ELAPSED] + +Ran 1 test suite [ELAPSED]: 2 tests passed, 0 failed, 0 skipped (2 total tests) + +"#]]); + + // Tested contract does not revert. + prj.add_source( + "Counter.sol", + r#" +contract Counter { + uint256 public number; + + function setNumber(uint256 newNumber) public { + number = newNumber; + } +} + "#, + ); + + // Tests should fail as revert happens in cheatcode (assert) and test (require) contract. + cmd.assert_failure().stdout_eq(str![[r#" +[COMPILING_FILES] with [SOLC_VERSION] +[SOLC_VERSION] [ELAPSED] +Compiler run successful! + +Ran 2 tests for test/CounterTest.t.sol:CounterTest +[FAIL: assertion failed: [..]] testFuzz_SetNumberAssert(uint256) (runs: 0, [AVG_GAS]) +[FAIL: EvmError: Revert; [..]] testFuzz_SetNumberRequire(uint256) (runs: 0, [AVG_GAS]) +Suite result: FAILED. 0 passed; 2 failed; 0 skipped; [ELAPSED] +... + +"#]]); +}); + +// Test 256 runs regardless number of test rejects. +// +forgetest_init!(test_fuzz_runs_with_rejects, |prj, cmd| { + prj.add_test( + "FuzzWithRejectsTest.t.sol", + r#" +import {Test} from "forge-std/Test.sol"; + +contract FuzzWithRejectsTest is Test { + function testFuzzWithRejects(uint256 x) public pure { + vm.assume(x < 1_000_000); + } +} + "#, + ); + + // Tests should not fail as revert happens in Counter contract. + cmd.args(["test", "--mc", "FuzzWithRejectsTest"]).assert_success().stdout_eq(str![[r#" +[COMPILING_FILES] with [SOLC_VERSION] +[SOLC_VERSION] [ELAPSED] +Compiler run successful! + +Ran 1 test for test/FuzzWithRejectsTest.t.sol:FuzzWithRejectsTest +[PASS] testFuzzWithRejects(uint256) (runs: 256, [AVG_GAS]) +Suite result: ok. 1 passed; 0 failed; 0 skipped; [ELAPSED] + +Ran 1 test suite [ELAPSED]: 1 tests passed, 0 failed, 0 skipped (1 total tests) + +"#]]); +}); + +// Test that counterexample is not replayed if test changes. +// +forgetest_init!(test_fuzz_replay_with_changed_test, |prj, cmd| { + prj.update_config(|config| config.fuzz.seed = Some(U256::from(100u32))); + prj.add_test( + "Counter.t.sol", + r#" +import {Test} from "forge-std/Test.sol"; + +contract CounterTest is Test { + function testFuzz_SetNumber(uint256 x) public pure { + require(x > 200); + } +} + "#, + ); + // Tests should fail and record counterexample with value 2. + cmd.args(["test"]).assert_failure().stdout_eq(str![[r#" +... +Failing tests: +Encountered 1 failing test in test/Counter.t.sol:CounterTest +[FAIL: EvmError: Revert; counterexample: calldata=0x5c7f60d70000000000000000000000000000000000000000000000000000000000000002 args=[2]] testFuzz_SetNumber(uint256) (runs: 19, [AVG_GAS]) +... + +"#]]); + + // Change test to assume counterexample 2 is discarded. + prj.add_test( + "Counter.t.sol", + r#" +import {Test} from "forge-std/Test.sol"; + +contract CounterTest is Test { + function testFuzz_SetNumber(uint256 x) public pure { + vm.assume(x != 2); + } +} + "#, + ); + // Test should pass when replay failure with changed assume logic. + cmd.forge_fuse().args(["test"]).assert_success().stdout_eq(str![[r#" +[COMPILING_FILES] with [SOLC_VERSION] +[SOLC_VERSION] [ELAPSED] +Compiler run successful! + +Ran 1 test for test/Counter.t.sol:CounterTest +[PASS] testFuzz_SetNumber(uint256) (runs: 256, [AVG_GAS]) +Suite result: ok. 1 passed; 0 failed; 0 skipped; [ELAPSED] + +Ran 1 test suite [ELAPSED]: 1 tests passed, 0 failed, 0 skipped (1 total tests) + +"#]]); + + // Change test signature. + prj.add_test( + "Counter.t.sol", + r#" +import {Test} from "forge-std/Test.sol"; + +contract CounterTest is Test { + function testFuzz_SetNumber(uint8 x) public pure { + } +} + "#, + ); + // Test should pass when replay failure with changed function signature. + cmd.forge_fuse().args(["test"]).assert_success().stdout_eq(str![[r#" +[COMPILING_FILES] with [SOLC_VERSION] +[SOLC_VERSION] [ELAPSED] +Compiler run successful! + +Ran 1 test for test/Counter.t.sol:CounterTest +[PASS] testFuzz_SetNumber(uint8) (runs: 256, [AVG_GAS]) +Suite result: ok. 1 passed; 0 failed; 0 skipped; [ELAPSED] + +Ran 1 test suite [ELAPSED]: 1 tests passed, 0 failed, 0 skipped (1 total tests) + +"#]]); + + // Change test back to the original one that produced the counterexample. + prj.add_test( + "Counter.t.sol", + r#" +import {Test} from "forge-std/Test.sol"; + +contract CounterTest is Test { + function testFuzz_SetNumber(uint256 x) public pure { + require(x > 200); + } +} + "#, + ); + // Test should fail with replayed counterexample 2 (0 runs). + cmd.forge_fuse().args(["test"]).assert_failure().stdout_eq(str![[r#" +... +Failing tests: +Encountered 1 failing test in test/Counter.t.sol:CounterTest +[FAIL: EvmError: Revert; counterexample: calldata=0x5c7f60d70000000000000000000000000000000000000000000000000000000000000002 args=[2]] testFuzz_SetNumber(uint256) (runs: 0, [AVG_GAS]) +... + +"#]]); +}); + +forgetest_init!(fuzz_basic, |prj, cmd| { + prj.wipe_contracts(); + prj.add_test( + "Fuzz.t.sol", + r#" +import "forge-std/Test.sol"; + +contract FuzzTest is Test { + constructor() { + emit log("constructor"); + } + + function setUp() public { + emit log("setUp"); + } + + function testShouldFailFuzz(uint8 x) public { + emit log("testFailFuzz"); + require(x > 128, "should revert"); + } + + function testSuccessfulFuzz(uint128 a, uint128 b) public { + emit log("testSuccessfulFuzz"); + assertEq(uint256(a) + uint256(b), uint256(a) + uint256(b)); + } + + function testToStringFuzz(bytes32 data) public { + vm.toString(data); + } +} + "#, + ); + + cmd.args(["test"]).assert_failure().stdout_eq(str![[r#" +... +Ran 3 tests for test/Fuzz.t.sol:FuzzTest +[FAIL: should revert; counterexample: calldata=[..] args=[..]] testShouldFailFuzz(uint8) (runs: [..], [AVG_GAS]) +[PASS] testSuccessfulFuzz(uint128,uint128) (runs: 256, [AVG_GAS]) +[PASS] testToStringFuzz(bytes32) (runs: 256, [AVG_GAS]) +Suite result: FAILED. 2 passed; 1 failed; 0 skipped; [ELAPSED] + +Ran 1 test suite [ELAPSED]: 2 tests passed, 1 failed, 0 skipped (3 total tests) + +Failing tests: +Encountered 1 failing test in test/Fuzz.t.sol:FuzzTest +[FAIL: should revert; counterexample: calldata=[..] args=[..]] testShouldFailFuzz(uint8) (runs: [..], [AVG_GAS]) + +Encountered a total of 1 failing tests, 2 tests succeeded + +Tip: Run `forge test --rerun` to retry only the 1 failed test + +"#]]); +}); + +// Test that showcases PUSH collection on normal fuzzing. +// Ignored until we collect them in a smarter way. +forgetest_init!( + #[ignore] + fuzz_collection, + |prj, cmd| { + prj.wipe_contracts(); + prj.update_config(|config| { + config.invariant.depth = 100; + config.invariant.runs = 1000; + config.fuzz.runs = 1000; + config.fuzz.seed = Some(U256::from(6u32)); + }); + prj.add_test( + "FuzzCollection.t.sol", + r#" +import "forge-std/Test.sol"; + +contract SampleContract { + uint256 public counter; + uint256 public counterX2; + address public owner = address(0xBEEF); + bool public found_needle; + + event Incremented(uint256 counter); + + modifier onlyOwner() { + require(msg.sender == owner, "ONLY_OWNER"); + _; + } + + function compare(uint256 val) public { + if (val == 0x4446) { + found_needle = true; + } + } + + function incrementBy(uint256 numToIncrement) public onlyOwner { + counter += numToIncrement; + counterX2 += numToIncrement * 2; + + emit Incremented(counter); + } + + function breakTheInvariant(uint256 x) public { + if (x == 0x5556) { + counterX2 = 0; + } + } +} + +contract SampleContractTest is Test { + event Incremented(uint256 counter); + + SampleContract public sample; + + function setUp() public { + sample = new SampleContract(); + } + + function testIncrement(address caller) public { + vm.startPrank(address(caller)); + + vm.expectRevert("ONLY_OWNER"); + sample.incrementBy(1); + } + + function testNeedle(uint256 needle) public { + sample.compare(needle); + require(!sample.found_needle(), "needle found."); + } + + function invariantCounter() public { + require(sample.counter() * 2 == sample.counterX2(), "broken counter."); + } +} + "#, + ); + + cmd.args(["test"]).assert_failure().stdout_eq(str![[r#""#]]); + } +); + +forgetest_init!(fuzz_failure_persist, |prj, cmd| { + prj.wipe_contracts(); + + let persist_dir = prj.cache().parent().unwrap().join("persist"); + assert!(!persist_dir.exists()); + prj.update_config(|config| { + config.fuzz.failure_persist_dir = Some(persist_dir.clone()); + }); + + prj.add_test( + "FuzzFailurePersist.t.sol", + r#" +import "forge-std/Test.sol"; + +struct TestTuple { + address user; + uint256 amount; +} + +contract FuzzFailurePersistTest is Test { + function test_persist_fuzzed_failure( + uint256 x, + int256 y, + address addr, + bool cond, + string calldata test, + TestTuple calldata tuple, + address[] calldata addresses + ) public { + // dummy assume to trigger runs + vm.assume(x > 1 && x < 1111111111111111111111111111); + vm.assume(y > 1 && y < 1111111111111111111111111111); + require(false); + } +} + "#, + ); + + let mut calldata = None; + let expected = str![[r#" +... +Ran 1 test for test/FuzzFailurePersist.t.sol:FuzzFailurePersistTest +[FAIL: EvmError: Revert; counterexample: calldata=[..] args=[..]] test_persist_fuzzed_failure(uint256,int256,address,bool,string,(address,uint256),address[]) (runs: 0, [AVG_GAS]) +Suite result: FAILED. 0 passed; 1 failed; 0 skipped; [ELAPSED] +... +"#]]; + let mut check = |cmd: &mut TestCommand, same: bool| { + let assert = cmd.assert_failure(); + let output = assert.get_output(); + let stdout = String::from_utf8_lossy(&output.stdout); + let calldata = calldata.get_or_insert_with(|| { + let re = Regex::new(r"calldata=(0x[0-9a-fA-F]+)").unwrap(); + re.captures(&stdout).unwrap().get(1).unwrap().as_str().to_string() + }); + assert_eq!(stdout.contains(calldata.as_str()), same, "\n{stdout}"); + assert.stdout_eq(expected.clone()); + }; + + cmd.arg("test"); + + // Run several times, asserting that the failure persists and is the same. + for _ in 0..3 { + check(&mut cmd, true); + assert!(persist_dir.exists()); + } + + // Change dir and run again, asserting that the failure persists. It should be a new failure. + let new_persist_dir = prj.cache().parent().unwrap().join("persist2"); + assert!(!new_persist_dir.exists()); + prj.update_config(|config| { + config.fuzz.failure_persist_dir = Some(new_persist_dir.clone()); + }); + check(&mut cmd, false); + assert!(new_persist_dir.exists()); +}); + +// https://github.com/foundry-rs/foundry/pull/735 behavior changed with https://github.com/foundry-rs/foundry/issues/3521 +// random values (instead edge cases) are generated if no fixtures defined +forgetest_init!(fuzz_int, |prj, cmd| { + prj.wipe_contracts(); + prj.add_test( + "FuzzInt.t.sol", + r#" +import "forge-std/Test.sol"; + +contract FuzzNumbersTest is Test { + function testPositive(int256) public { + assertTrue(true); + } + + function testNegativeHalf(int256 val) public { + assertTrue(val < 2 ** 128 - 1); + } + + function testNegative0(int256 val) public { + assertTrue(val == 0); + } + + function testNegative1(int256 val) public { + assertTrue(val == -1); + } + + function testNegative2(int128 val) public { + assertTrue(val == 1); + } + + function testNegativeMax0(int256 val) public { + assertTrue(val == type(int256).max); + } + + function testNegativeMax1(int256 val) public { + assertTrue(val == type(int256).max - 2); + } + + function testNegativeMin0(int256 val) public { + assertTrue(val == type(int256).min); + } + + function testNegativeMin1(int256 val) public { + assertTrue(val == type(int256).min + 2); + } + + function testEquality(int256 x, int256 y) public { + int256 xy; + + unchecked { + xy = x * y; + } + + if ((x != 0 && xy / x != y)) { + return; + } + + assertEq(((xy - 1) / 1e18) + 1, (xy - 1) / (1e18 + 1)); + } +} + "#, + ); + + cmd.args(["test"]).assert_failure().stdout_eq(str![[r#" +... +Ran 10 tests for test/FuzzInt.t.sol:FuzzNumbersTest +[FAIL: assertion failed[..]] testEquality(int256,int256) (runs: [..], [AVG_GAS]) +[FAIL: assertion failed[..]] testNegative0(int256) (runs: [..], [AVG_GAS]) +[FAIL: assertion failed[..]] testNegative1(int256) (runs: [..], [AVG_GAS]) +[FAIL: assertion failed[..]] testNegative2(int128) (runs: [..], [AVG_GAS]) +[FAIL: assertion failed[..]] testNegativeHalf(int256) (runs: [..], [AVG_GAS]) +[FAIL: assertion failed[..]] testNegativeMax0(int256) (runs: [..], [AVG_GAS]) +[FAIL: assertion failed[..]] testNegativeMax1(int256) (runs: [..], [AVG_GAS]) +[FAIL: assertion failed[..]] testNegativeMin0(int256) (runs: [..], [AVG_GAS]) +[FAIL: assertion failed[..]] testNegativeMin1(int256) (runs: [..], [AVG_GAS]) +[PASS] testPositive(int256) (runs: 256, [AVG_GAS]) +Suite result: FAILED. 1 passed; 9 failed; 0 skipped; [ELAPSED] + +Ran 1 test suite [ELAPSED]: 1 tests passed, 9 failed, 0 skipped (10 total tests) +... +"#]]); +}); + +forgetest_init!(fuzz_positive, |prj, cmd| { + prj.wipe_contracts(); + prj.add_test( + "FuzzPositive.t.sol", + r#" +import "forge-std/Test.sol"; + +contract FuzzPositive is Test { + function testSuccessChecker(uint256 val) public { + assertTrue(true); + } + + function testSuccessChecker2(int256 val) public { + assert(val == val); + } + + function testSuccessChecker3(uint32 val) public { + assert(val + 0 == val); + } +} + "#, + ); + + cmd.args(["test"]).assert_success().stdout_eq(str![[r#" +... +Ran 3 tests for test/FuzzPositive.t.sol:FuzzPositive +[PASS] testSuccessChecker(uint256) (runs: 256, [AVG_GAS]) +[PASS] testSuccessChecker2(int256) (runs: 256, [AVG_GAS]) +[PASS] testSuccessChecker3(uint32) (runs: 256, [AVG_GAS]) +Suite result: ok. 3 passed; 0 failed; 0 skipped; [ELAPSED] + +Ran 1 test suite [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) + +"#]]); +}); + +// https://github.com/foundry-rs/foundry/pull/735 behavior changed with https://github.com/foundry-rs/foundry/issues/3521 +// random values (instead edge cases) are generated if no fixtures defined +forgetest_init!(fuzz_uint, |prj, cmd| { + prj.wipe_contracts(); + prj.add_test( + "FuzzUint.t.sol", + r#" +import "forge-std/Test.sol"; + +contract FuzzNumbersTest is Test { + function testPositive(uint256) public { + assertTrue(true); + } + + function testNegativeHalf(uint256 val) public { + assertTrue(val < 2 ** 128 - 1); + } + + function testNegative0(uint256 val) public { + assertTrue(val == 0); + } + + function testNegative2(uint256 val) public { + assertTrue(val == 2); + } + + function testNegative2Max(uint256 val) public { + assertTrue(val == type(uint256).max - 2); + } + + function testNegativeMax(uint256 val) public { + assertTrue(val == type(uint256).max); + } + + function testEquality(uint256 x, uint256 y) public { + uint256 xy; + + unchecked { + xy = x * y; + } + + if ((x != 0 && xy / x != y)) { + return; + } + + assertEq(((xy - 1) / 1e18) + 1, (xy - 1) / (1e18 + 1)); + } +} + "#, + ); + + cmd.args(["test"]).assert_failure().stdout_eq(str![[r#" +... +Ran 7 tests for test/FuzzUint.t.sol:FuzzNumbersTest +[FAIL: assertion failed[..]] testEquality(uint256,uint256) (runs: [..], [AVG_GAS]) +[FAIL: assertion failed[..]] testNegative0(uint256) (runs: [..], [AVG_GAS]) +[FAIL: assertion failed[..]] testNegative2(uint256) (runs: [..], [AVG_GAS]) +[FAIL: assertion failed[..]] testNegative2Max(uint256) (runs: [..], [AVG_GAS]) +[FAIL: assertion failed[..]] testNegativeHalf(uint256) (runs: [..], [AVG_GAS]) +[FAIL: assertion failed[..]] testNegativeMax(uint256) (runs: [..], [AVG_GAS]) +[PASS] testPositive(uint256) (runs: 256, [AVG_GAS]) +Suite result: FAILED. 1 passed; 6 failed; 0 skipped; [ELAPSED] +... +"#]]); +}); diff --git a/crates/forge/tests/cli/test_cmd/invariant/common.rs b/crates/forge/tests/cli/test_cmd/invariant/common.rs new file mode 100644 index 0000000000000..4e32bf143fb58 --- /dev/null +++ b/crates/forge/tests/cli/test_cmd/invariant/common.rs @@ -0,0 +1,1424 @@ +use super::*; + +forgetest!(invariant_after_invariant, |prj, cmd| { + prj.insert_vm(); + prj.insert_ds_test(); + + prj.add_test( + "InvariantAfterInvariant.t.sol", + r#" +import { DSTest as Test } from "src/test.sol"; + +struct FuzzSelector { + address addr; + bytes4[] selectors; +} + +contract AfterInvariantHandler { + uint256 public count; + + function inc() external { + count += 1; + } +} + +contract InvariantAfterInvariantTest is Test { + AfterInvariantHandler handler; + + function setUp() public { + handler = new AfterInvariantHandler(); + } + + function targetSelectors() public returns (FuzzSelector[] memory) { + FuzzSelector[] memory targets = new FuzzSelector[](1); + bytes4[] memory selectors = new bytes4[](1); + selectors[0] = handler.inc.selector; + targets[0] = FuzzSelector(address(handler), selectors); + return targets; + } + + function afterInvariant() public { + require(handler.count() < 10, "afterInvariant failure"); + } + + /// forge-config: default.invariant.runs = 1 + /// forge-config: default.invariant.depth = 11 + function invariant_after_invariant_failure() public view { + require(handler.count() < 20, "invariant after invariant failure"); + } + + /// forge-config: default.invariant.runs = 1 + /// forge-config: default.invariant.depth = 11 + function invariant_failure() public view { + require(handler.count() < 9, "invariant failure"); + } + + /// forge-config: default.invariant.runs = 1 + /// forge-config: default.invariant.depth = 5 + function invariant_success() public view { + require(handler.count() < 11, "invariant should not fail"); + } +} +"#, + ); + + assert_invariant(cmd.args(["test"])).failure().stdout_eq(str![[r#" +... +Ran 3 tests for test/InvariantAfterInvariant.t.sol:InvariantAfterInvariantTest +[FAIL: afterInvariant failure] + [SEQUENCE] + invariant_after_invariant_failure() ([RUNS]) + +[STATS] + +[FAIL: invariant failure] + [SEQUENCE] + invariant_failure() ([RUNS]) + +[STATS] + +[PASS] invariant_success() ([RUNS]) + +[STATS] + +Suite result: FAILED. 1 passed; 2 failed; 0 skipped; [ELAPSED] + +Ran 1 test suite [ELAPSED]: 1 tests passed, 2 failed, 0 skipped (3 total tests) + +Failing tests: +Encountered 2 failing tests in test/InvariantAfterInvariant.t.sol:InvariantAfterInvariantTest +[FAIL: afterInvariant failure] + [SEQUENCE] + invariant_after_invariant_failure() ([RUNS]) +[FAIL: invariant failure] + [SEQUENCE] + invariant_failure() ([RUNS]) + +Encountered a total of 2 failing tests, 1 tests succeeded + +Tip: Run `forge test --rerun` to retry only the 2 failed tests + +"#]]); +}); + +forgetest_init!(invariant_assume, |prj, cmd| { + prj.wipe_contracts(); + prj.update_config(|config| { + config.invariant.runs = 1; + config.invariant.depth = 10; + // Should not treat vm.assume as revert. + config.invariant.fail_on_revert = true; + }); + + prj.add_test( + "InvariantAssume.t.sol", + r#" +import "forge-std/Test.sol"; + +contract Handler is Test { + function doSomething(uint256 param) public { + vm.assume(param == 0); + } +} + +contract InvariantAssume is Test { + Handler handler; + + function setUp() public { + handler = new Handler(); + } + + function invariant_dummy() public {} +} +"#, + ); + + assert_invariant(cmd.args(["test"])).success().stdout_eq(str![[r#" +[COMPILING_FILES] with [SOLC_VERSION] +[SOLC_VERSION] [ELAPSED] +Compiler run successful with warnings: +Warning (2018): Function state mutability can be restricted to pure + [FILE]:7:5: + | +7 | function doSomething(uint256 param) public { + | ^ (Relevant source part starts here and spans across multiple lines). + + +Ran 1 test for test/InvariantAssume.t.sol:InvariantAssume +[PASS] invariant_dummy() ([RUNS]) + +[STATS] + +Suite result: ok. 1 passed; 0 failed; 0 skipped; [ELAPSED] + +Ran 1 test suite [ELAPSED]: 1 tests passed, 0 failed, 0 skipped (1 total tests) + +"#]]); + + // Test that max_assume_rejects is respected. + prj.update_config(|config| { + config.invariant.max_assume_rejects = 1; + }); + + assert_invariant(&mut cmd).failure().stdout_eq(str![[r#" +No files changed, compilation skipped + +Ran 1 test for test/InvariantAssume.t.sol:InvariantAssume +[FAIL: `vm.assume` rejected too many inputs (1 allowed)] invariant_dummy() ([RUNS]) + +[STATS] + +Suite result: FAILED. 0 passed; 1 failed; 0 skipped; [ELAPSED] + +Ran 1 test suite [ELAPSED]: 0 tests passed, 1 failed, 0 skipped (1 total tests) + +Failing tests: +Encountered 1 failing test in test/InvariantAssume.t.sol:InvariantAssume +[FAIL: `vm.assume` rejected too many inputs (1 allowed)] invariant_dummy() ([RUNS]) + +Encountered a total of 1 failing tests, 0 tests succeeded + +Tip: Run `forge test --rerun` to retry only the 1 failed test + +"#]]); +}); + +// https://github.com/foundry-rs/foundry/issues/5868 +forgetest!(invariant_calldata_dictionary, |prj, cmd| { + prj.wipe_contracts(); + prj.insert_utils(); + prj.update_config(|config| { + config.invariant.depth = 10; + }); + + prj.add_test( + "InvariantCalldataDictionary.t.sol", + r#" +import "./utils/Test.sol"; + +struct FuzzSelector { + address addr; + bytes4[] selectors; +} + +contract Owned { + address public owner; + address private ownerCandidate; + + constructor() { + owner = msg.sender; + } + + modifier onlyOwner() { + require(msg.sender == owner); + _; + } + + modifier onlyOwnerCandidate() { + require(msg.sender == ownerCandidate); + _; + } + + function transferOwnership(address candidate) external onlyOwner { + ownerCandidate = candidate; + } + + function acceptOwnership() external onlyOwnerCandidate { + owner = ownerCandidate; + } +} + +contract Handler is Test { + Owned owned; + + constructor(Owned _owned) { + owned = _owned; + } + + function transferOwnership(address sender, address candidate) external { + vm.assume(sender != address(0)); + vm.prank(sender); + owned.transferOwnership(candidate); + } + + function acceptOwnership(address sender) external { + vm.assume(sender != address(0)); + vm.prank(sender); + owned.acceptOwnership(); + } +} + +contract InvariantCalldataDictionary is Test { + address owner; + Owned owned; + Handler handler; + address[] actors; + + function setUp() public { + owner = address(this); + owned = new Owned(); + handler = new Handler(owned); + actors.push(owner); + actors.push(address(777)); + } + + function targetSelectors() public returns (FuzzSelector[] memory) { + FuzzSelector[] memory targets = new FuzzSelector[](1); + bytes4[] memory selectors = new bytes4[](2); + selectors[0] = handler.transferOwnership.selector; + selectors[1] = handler.acceptOwnership.selector; + targets[0] = FuzzSelector(address(handler), selectors); + return targets; + } + + function fixtureSender() external returns (address[] memory) { + return actors; + } + + function fixtureCandidate() external returns (address[] memory) { + return actors; + } + + function invariant_owner_never_changes() public { + assertEq(owned.owner(), owner); + } +} +"#, + ); + + assert_invariant(cmd.args(["test"])).failure().stdout_eq(str![[r#" +... +Ran 1 test for test/InvariantCalldataDictionary.t.sol:InvariantCalldataDictionary +[FAIL: ] + [SEQUENCE] + invariant_owner_never_changes() ([RUNS]) + +[STATS] + +Suite result: FAILED. 0 passed; 1 failed; 0 skipped; [ELAPSED] + +Ran 1 test suite [ELAPSED]: 0 tests passed, 1 failed, 0 skipped (1 total tests) + +Failing tests: +Encountered 1 failing test in test/InvariantCalldataDictionary.t.sol:InvariantCalldataDictionary +[FAIL: ] + [SEQUENCE] + invariant_owner_never_changes() ([RUNS]) + +Encountered a total of 1 failing tests, 0 tests succeeded + +Tip: Run `forge test --rerun` to retry only the 1 failed test + +"#]]); +}); + +forgetest_init!(invariant_custom_error, |prj, cmd| { + prj.wipe_contracts(); + prj.update_config(|config| { + config.invariant.depth = 10; + config.invariant.fail_on_revert = true; + }); + + prj.add_test( + "InvariantCustomError.t.sol", + r#" +import "forge-std/Test.sol"; + +contract ContractWithCustomError { + error InvariantCustomError(uint256, string); + + function revertWithInvariantCustomError() external { + revert InvariantCustomError(111, "custom"); + } +} + +contract Handler is Test { + ContractWithCustomError target; + + constructor() { + target = new ContractWithCustomError(); + } + + function revertTarget() external { + target.revertWithInvariantCustomError(); + } +} + +contract InvariantCustomError is Test { + Handler handler; + + function setUp() external { + handler = new Handler(); + } + + function invariant_decode_error() public {} +} +"#, + ); + + assert_invariant(cmd.args(["test"])).failure().stdout_eq(str![[r#" +... +Ran 1 test for test/InvariantCustomError.t.sol:InvariantCustomError +[FAIL: InvariantCustomError(111, "custom")] + [SEQUENCE] + invariant_decode_error() ([RUNS]) + +[STATS] + +Suite result: FAILED. 0 passed; 1 failed; 0 skipped; [ELAPSED] + +Ran 1 test suite [ELAPSED]: 0 tests passed, 1 failed, 0 skipped (1 total tests) + +Failing tests: +Encountered 1 failing test in test/InvariantCustomError.t.sol:InvariantCustomError +[FAIL: InvariantCustomError(111, "custom")] + [SEQUENCE] + invariant_decode_error() ([RUNS]) + +Encountered a total of 1 failing tests, 0 tests succeeded + +Tip: Run `forge test --rerun` to retry only the 1 failed test + +"#]]); +}); + +forgetest_init!(invariant_excluded_senders, |prj, cmd| { + prj.wipe_contracts(); + prj.update_config(|config| { + config.invariant.depth = 10; + config.invariant.fail_on_revert = true; + }); + + prj.add_test( + "InvariantExcludedSenders.t.sol", + r#" +import "forge-std/Test.sol"; + +contract InvariantSenders { + function checkSender() external { + require(msg.sender != 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D, "sender cannot be cheatcode address"); + require(msg.sender != 0x000000000000000000636F6e736F6c652e6c6f67, "sender cannot be console address"); + require(msg.sender != 0x4e59b44847b379578588920cA78FbF26c0B4956C, "sender cannot be CREATE2 deployer"); + } +} + +contract InvariantExcludedSendersTest is Test { + InvariantSenders target; + + function setUp() public { + target = new InvariantSenders(); + } + + function invariant_check_sender() public view {} +} +"#, + ); + + assert_invariant(cmd.args(["test"])).success().stdout_eq(str![[r#" +[COMPILING_FILES] with [SOLC_VERSION] +[SOLC_VERSION] [ELAPSED] +Compiler run successful with warnings: +Warning (2018): Function state mutability can be restricted to view + [FILE]:7:5: + | +7 | function checkSender() external { + | ^ (Relevant source part starts here and spans across multiple lines). + + +Ran 1 test for test/InvariantExcludedSenders.t.sol:InvariantExcludedSendersTest +[PASS] invariant_check_sender() ([RUNS]) + +[STATS] + +Suite result: ok. 1 passed; 0 failed; 0 skipped; [ELAPSED] + +Ran 1 test suite [ELAPSED]: 1 tests passed, 0 failed, 0 skipped (1 total tests) + +"#]]); +}); + +forgetest_init!(invariant_fixtures, |prj, cmd| { + prj.wipe_contracts(); + prj.update_config(|config| { + config.invariant.runs = 1; + config.invariant.depth = 100; + }); + + prj.add_test( + "InvariantFixtures.t.sol", + r#" +import "forge-std/Test.sol"; + +contract Target { + bool ownerFound; + bool amountFound; + bool magicFound; + bool keyFound; + bool backupFound; + bool extraStringFound; + + function fuzzWithFixtures( + address owner_, + uint256 _amount, + int32 magic, + bytes32 key, + bytes memory backup, + string memory extra + ) external { + if (owner_ == address(0x6B175474E89094C44Da98b954EedeAC495271d0F)) { + ownerFound = true; + } + if (_amount == 1122334455) amountFound = true; + if (magic == -777) magicFound = true; + if (key == "abcd1234") keyFound = true; + if (keccak256(backup) == keccak256("qwerty1234")) backupFound = true; + if (keccak256(abi.encodePacked(extra)) == keccak256(abi.encodePacked("112233aabbccdd"))) { + extraStringFound = true; + } + } + + function isCompromised() public view returns (bool) { + return ownerFound && amountFound && magicFound && keyFound && backupFound && extraStringFound; + } +} + +/// Try to compromise target contract by finding all accepted values using fixtures. +contract InvariantFixtures is Test { + Target target; + address[] public fixture_owner_ = [address(0x6B175474E89094C44Da98b954EedeAC495271d0F)]; + uint256[] public fixture_amount = [1, 2, 1122334455]; + + function setUp() public { + target = new Target(); + } + + function fixtureMagic() external returns (int32[2] memory) { + int32[2] memory magic; + magic[0] = -777; + magic[1] = 777; + return magic; + } + + function fixtureKey() external pure returns (bytes32[] memory) { + bytes32[] memory keyFixture = new bytes32[](1); + keyFixture[0] = "abcd1234"; + return keyFixture; + } + + function fixtureBackup() external pure returns (bytes[] memory) { + bytes[] memory backupFixture = new bytes[](1); + backupFixture[0] = "qwerty1234"; + return backupFixture; + } + + function fixtureExtra() external pure returns (string[] memory) { + string[] memory extraFixture = new string[](1); + extraFixture[0] = "112233aabbccdd"; + return extraFixture; + } + + function invariant_target_not_compromised() public { + assertEq(target.isCompromised(), false); + } +} +"#, + ); + + assert_invariant(cmd.args(["test"])).failure().stdout_eq(str![[r#" +... +Ran 1 test for test/InvariantFixtures.t.sol:InvariantFixtures +[FAIL: assertion failed: true != false] + [SEQUENCE] + invariant_target_not_compromised() ([RUNS]) + +[STATS] + +Suite result: FAILED. 0 passed; 1 failed; 0 skipped; [ELAPSED] + +Ran 1 test suite [ELAPSED]: 0 tests passed, 1 failed, 0 skipped (1 total tests) + +Failing tests: +Encountered 1 failing test in test/InvariantFixtures.t.sol:InvariantFixtures +[FAIL: assertion failed: true != false] + [SEQUENCE] + invariant_target_not_compromised() ([RUNS]) + +Encountered a total of 1 failing tests, 0 tests succeeded + +Tip: Run `forge test --rerun` to retry only the 1 failed test + +"#]]); +}); + +forgetest!(invariant_handler_failure, |prj, cmd| { + prj.insert_utils(); + prj.update_config(|config| { + config.invariant.fail_on_revert = true; + config.invariant.runs = 1; + config.invariant.depth = 10; + }); + + prj.add_test( + "InvariantHandlerFailure.t.sol", + r#" +import "./utils/Test.sol"; + +struct FuzzSelector { + address addr; + bytes4[] selectors; +} + +contract Handler is Test { + function doSomething() public { + require(false, "failed on revert"); + } +} + +contract InvariantHandlerFailure is Test { + bytes4[] internal selectors; + + Handler handler; + + function targetSelectors() public returns (FuzzSelector[] memory) { + FuzzSelector[] memory targets = new FuzzSelector[](1); + bytes4[] memory selectors = new bytes4[](1); + selectors[0] = handler.doSomething.selector; + targets[0] = FuzzSelector(address(handler), selectors); + return targets; + } + + function setUp() public { + handler = new Handler(); + } + + function statefulFuzz_BrokenInvariant() public {} +} +"#, + ); + + assert_invariant(cmd.args(["test"])).failure().stdout_eq(str![[r#" +... +Ran 1 test for test/InvariantHandlerFailure.t.sol:InvariantHandlerFailure +[FAIL: failed on revert] + [SEQUENCE] + statefulFuzz_BrokenInvariant() ([RUNS]) + +[STATS] + +Suite result: FAILED. 0 passed; 1 failed; 0 skipped; [ELAPSED] + +Ran 1 test suite [ELAPSED]: 0 tests passed, 1 failed, 0 skipped (1 total tests) + +Failing tests: +Encountered 1 failing test in test/InvariantHandlerFailure.t.sol:InvariantHandlerFailure +[FAIL: failed on revert] + [SEQUENCE] + statefulFuzz_BrokenInvariant() ([RUNS]) + +Encountered a total of 1 failing tests, 0 tests succeeded + +Tip: Run `forge test --rerun` to retry only the 1 failed test + +"#]]); +}); + +// Here we test that the fuzz engine can include a contract created during the fuzz +// in its fuzz dictionary and eventually break the invariant. +// Specifically, can Judas, a created contract from Jesus, break Jesus contract +// by revealing his identity. +forgetest_init!( + #[cfg_attr(windows, ignore = "for some reason there's different rng")] + invariant_inner_contract, + |prj, cmd| { + prj.wipe_contracts(); + prj.update_config(|config| { + config.invariant.depth = 10; + }); + + prj.add_test( + "InvariantInnerContract.t.sol", + r#" +import "forge-std/Test.sol"; + +contract Jesus { + address fren; + bool public identity_revealed; + + function create_fren() public { + fren = address(new Judas()); + } + + function kiss() public { + require(msg.sender == fren); + identity_revealed = true; + } +} + +contract Judas { + Jesus jesus; + + constructor() { + jesus = Jesus(msg.sender); + } + + function betray() public { + jesus.kiss(); + } +} + +contract InvariantInnerContract is Test { + Jesus jesus; + + function setUp() public { + jesus = new Jesus(); + } + + function invariantHideJesus() public { + require(jesus.identity_revealed() == false, "jesus betrayed"); + } +} +"#, + ); + + assert_invariant(cmd.args(["test"])).failure().stdout_eq(str![[r#" +... +Ran 1 test for test/InvariantInnerContract.t.sol:InvariantInnerContract +[FAIL: jesus betrayed] + [SEQUENCE] + invariantHideJesus() ([RUNS]) + +[STATS] + +Suite result: FAILED. 0 passed; 1 failed; 0 skipped; [ELAPSED] + +Ran 1 test suite [ELAPSED]: 0 tests passed, 1 failed, 0 skipped (1 total tests) + +Failing tests: +Encountered 1 failing test in test/InvariantInnerContract.t.sol:InvariantInnerContract +[FAIL: jesus betrayed] + [SEQUENCE] + invariantHideJesus() ([RUNS]) + +Encountered a total of 1 failing tests, 0 tests succeeded + +Tip: Run `forge test --rerun` to retry only the 1 failed test + +"#]]); + + // `fuzz_seed` at 119 makes this sequence shrinkable from 4 to 2. + prj.update_config(|config| { + config.fuzz.seed = Some(U256::from(119u32)); + // Disable persisted failures for rerunning the test. + config.invariant.failure_persist_dir = Some( + config + .invariant + .failure_persist_dir + .as_ref() + .unwrap() + .parent() + .unwrap() + .join("persistence2"), + ); + }); + cmd.assert_failure().stdout_eq(str![[r#" +No files changed, compilation skipped + +Ran 1 test for test/InvariantInnerContract.t.sol:InvariantInnerContract +[FAIL: jesus betrayed] + [Sequence] (original: 2, shrunk: 2) + sender=[..] addr=[test/InvariantInnerContract.t.sol:Jesus][..] calldata=create_fren() args=[] + sender=[..] addr=[test/InvariantInnerContract.t.sol:Judas][..] calldata=betray() args=[] + invariantHideJesus() (runs: 0, calls: 0, reverts: 1) +... +"#]]); + } +); + +// https://github.com/foundry-rs/foundry/issues/7219 +forgetest!(invariant_preserve_state, |prj, cmd| { + prj.insert_utils(); + prj.update_config(|config| { + config.invariant.depth = 10; + config.invariant.fail_on_revert = true; + }); + + prj.add_test( + "InvariantPreserveState.t.sol", + r#" +import "./utils/Test.sol"; + +struct FuzzSelector { + address addr; + bytes4[] selectors; +} + +contract Handler is Test { + function thisFunctionReverts() external { + if (block.number < 10) {} else { + revert(); + } + } + + function advanceTime(uint256 blocks) external { + blocks = blocks % 10; + vm.roll(block.number + blocks); + vm.warp(block.timestamp + blocks * 12); + } +} + +contract InvariantPreserveState is Test { + Handler handler; + + function setUp() public { + handler = new Handler(); + } + + function targetSelectors() public returns (FuzzSelector[] memory) { + FuzzSelector[] memory targets = new FuzzSelector[](1); + bytes4[] memory selectors = new bytes4[](2); + selectors[0] = handler.thisFunctionReverts.selector; + selectors[1] = handler.advanceTime.selector; + targets[0] = FuzzSelector(address(handler), selectors); + return targets; + } + + function invariant_preserve_state() public { + assertTrue(true); + } +} +"#, + ); + + assert_invariant(cmd.args(["test"])).failure().stdout_eq(str![[r#" +... +Ran 1 test for test/InvariantPreserveState.t.sol:InvariantPreserveState +[FAIL: EvmError: Revert] + [SEQUENCE] + invariant_preserve_state() ([RUNS]) + +[STATS] + +Suite result: FAILED. 0 passed; 1 failed; 0 skipped; [ELAPSED] + +Ran 1 test suite [ELAPSED]: 0 tests passed, 1 failed, 0 skipped (1 total tests) + +Failing tests: +Encountered 1 failing test in test/InvariantPreserveState.t.sol:InvariantPreserveState +[FAIL: EvmError: Revert] + [SEQUENCE] + invariant_preserve_state() ([RUNS]) + +Encountered a total of 1 failing tests, 0 tests succeeded + +Tip: Run `forge test --rerun` to retry only the 1 failed test + +"#]]); +}); + +// add code so contract is accounted as valid sender +// see https://github.com/foundry-rs/foundry/issues/4245 +forgetest!(invariant_reentrancy, |prj, cmd| { + prj.insert_utils(); + prj.update_config(|config| { + config.invariant.depth = 10; + config.invariant.fail_on_revert = false; + config.invariant.call_override = true; + }); + + prj.add_test( + "InvariantReentrancy.t.sol", + r#" +import "./utils/Test.sol"; + +contract Malicious { + function world() public { + payable(msg.sender).call(""); + } +} + +contract Vulnerable { + bool public open_door = false; + bool public stolen = false; + Malicious mal; + + constructor(address _mal) { + mal = Malicious(_mal); + } + + function hello() public { + open_door = true; + mal.world(); + open_door = false; + } + + function backdoor() public { + require(open_door, ""); + stolen = true; + } +} + +contract InvariantReentrancy is Test { + Vulnerable vuln; + Malicious mal; + + function setUp() public { + mal = new Malicious(); + vuln = new Vulnerable(address(mal)); + } + + // do not include `mal` in identified contracts + // see https://github.com/foundry-rs/foundry/issues/4245 + function targetContracts() public view returns (address[] memory) { + address[] memory targets = new address[](1); + targets[0] = address(vuln); + return targets; + } + + function invariantNotStolen() public { + require(vuln.stolen() == false, "stolen"); + } +} +"#, + ); + + assert_invariant(cmd.args(["test"])).failure().stdout_eq(str![[r#" +... +Ran 1 test for test/InvariantReentrancy.t.sol:InvariantReentrancy +[FAIL: stolen] + [SEQUENCE] + invariantNotStolen() ([RUNS]) + +[STATS] + +Suite result: FAILED. 0 passed; 1 failed; 0 skipped; [ELAPSED] + +Ran 1 test suite [ELAPSED]: 0 tests passed, 1 failed, 0 skipped (1 total tests) + +Failing tests: +Encountered 1 failing test in test/InvariantReentrancy.t.sol:InvariantReentrancy +[FAIL: stolen] + [SEQUENCE] + invariantNotStolen() ([RUNS]) + +Encountered a total of 1 failing tests, 0 tests succeeded + +Tip: Run `forge test --rerun` to retry only the 1 failed test + +"#]]); +}); + +forgetest_init!(invariant_roll_fork, |prj, cmd| { + prj.wipe_contracts(); + prj.add_rpc_endpoints(); + prj.update_config(|config| { + config.fuzz.seed = Some(U256::from(119u32)); + }); + + prj.add_test( + "InvariantRollFork.t.sol", + r#" +import "forge-std/Test.sol"; + +interface IERC20 { + function totalSupply() external view returns (uint256 supply); +} + +contract RollForkHandler is Test { + uint256 public totalSupply; + + function work() external { + vm.rollFork(block.number + 1); + totalSupply = IERC20(0x6B175474E89094C44Da98b954EedeAC495271d0F).totalSupply(); + } +} + +contract InvariantRollForkBlockTest is Test { + RollForkHandler forkHandler; + + function setUp() public { + vm.createSelectFork("mainnet", 19812632); + forkHandler = new RollForkHandler(); + } + + /// forge-config: default.invariant.runs = 2 + /// forge-config: default.invariant.depth = 4 + function invariant_fork_handler_block() public { + require(block.number < 19812634, "too many blocks mined"); + } +} + +contract InvariantRollForkStateTest is Test { + RollForkHandler forkHandler; + + function setUp() public { + vm.createSelectFork("mainnet", 19812632); + forkHandler = new RollForkHandler(); + } + + /// forge-config: default.invariant.runs = 1 + function invariant_fork_handler_state() public { + require(forkHandler.totalSupply() < 3254378807384273078310283461, "wrong supply"); + } +} +"#, + ); + + assert_invariant(cmd.args(["test", "-j1"])).failure().stdout_eq(str![[r#" +... +Ran 1 test for test/InvariantRollFork.t.sol:InvariantRollForkBlockTest +[FAIL: too many blocks mined] + [SEQUENCE] + invariant_fork_handler_block() ([RUNS]) + +[STATS] + +Suite result: FAILED. 0 passed; 1 failed; 0 skipped; [ELAPSED] + +Ran 1 test for test/InvariantRollFork.t.sol:InvariantRollForkStateTest +[FAIL: wrong supply] + [SEQUENCE] + invariant_fork_handler_state() ([RUNS]) + +[STATS] + +Suite result: FAILED. 0 passed; 1 failed; 0 skipped; [ELAPSED] + +Ran 2 test suites [ELAPSED]: 0 tests passed, 2 failed, 0 skipped (2 total tests) + +Failing tests: +Encountered 1 failing test in test/InvariantRollFork.t.sol:InvariantRollForkBlockTest +[FAIL: too many blocks mined] + [SEQUENCE] + invariant_fork_handler_block() ([RUNS]) + +Encountered 1 failing test in test/InvariantRollFork.t.sol:InvariantRollForkStateTest +[FAIL: wrong supply] + [SEQUENCE] + invariant_fork_handler_state() ([RUNS]) + +Encountered a total of 2 failing tests, 0 tests succeeded + +Tip: Run `forge test --rerun` to retry only the 2 failed tests + +"#]]); +}); + +forgetest_init!(invariant_scrape_values, |prj, cmd| { + prj.wipe_contracts(); + prj.update_config(|config| { + config.invariant.depth = 10; + }); + + prj.add_test( + "InvariantScrapeValues.t.sol", + r#" +import "forge-std/Test.sol"; + +contract FindFromReturnValue { + bool public found = false; + + function seed() public returns (int256) { + int256 mystery = 13337; + return (1337 + mystery); + } + + function find(int256 i) public { + int256 mystery = 13337; + if (i == 1337 + mystery) { + found = true; + } + } +} + +contract FindFromReturnValueTest is Test { + FindFromReturnValue target; + + function setUp() public { + target = new FindFromReturnValue(); + } + + /// forge-config: default.invariant.runs = 50 + /// forge-config: default.invariant.depth = 300 + /// forge-config: default.invariant.fail-on-revert = true + function invariant_value_not_found() public view { + require(!target.found(), "value from return found"); + } +} + +contract FindFromLogValue { + event FindFromLog(int256 indexed mystery, bytes32 rand); + + bool public found = false; + + function seed() public { + int256 mystery = 13337; + emit FindFromLog(1337 + mystery, keccak256(abi.encodePacked("mystery"))); + } + + function find(int256 i) public { + int256 mystery = 13337; + if (i == 1337 + mystery) { + found = true; + } + } +} + +contract FindFromLogValueTest is Test { + FindFromLogValue target; + + function setUp() public { + target = new FindFromLogValue(); + } + + /// forge-config: default.invariant.runs = 50 + /// forge-config: default.invariant.depth = 300 + /// forge-config: default.invariant.fail-on-revert = true + function invariant_value_not_found() public view { + require(!target.found(), "value from logs found"); + } +} +"#, + ); + + assert_invariant(cmd.args(["test", "-j1"])).failure().stdout_eq(str![[r#" +... +Ran 1 test for test/InvariantScrapeValues.t.sol:FindFromLogValueTest +[FAIL: value from logs found] + [SEQUENCE] + invariant_value_not_found() ([RUNS]) + +[STATS] + +Suite result: FAILED. 0 passed; 1 failed; 0 skipped; [ELAPSED] + +Ran 1 test for test/InvariantScrapeValues.t.sol:FindFromReturnValueTest +[FAIL: value from return found] + [SEQUENCE] + invariant_value_not_found() ([RUNS]) + +[STATS] + +Suite result: FAILED. 0 passed; 1 failed; 0 skipped; [ELAPSED] + +Ran 2 test suites [ELAPSED]: 0 tests passed, 2 failed, 0 skipped (2 total tests) + +Failing tests: +Encountered 1 failing test in test/InvariantScrapeValues.t.sol:FindFromLogValueTest +[FAIL: value from logs found] + [SEQUENCE] + invariant_value_not_found() ([RUNS]) + +Encountered 1 failing test in test/InvariantScrapeValues.t.sol:FindFromReturnValueTest +[FAIL: value from return found] + [SEQUENCE] + invariant_value_not_found() ([RUNS]) + +Encountered a total of 2 failing tests, 0 tests succeeded + +Tip: Run `forge test --rerun` to retry only the 2 failed tests + +"#]]); +}); + +forgetest_init!(invariant_sequence_no_reverts, |prj, cmd| { + prj.wipe_contracts(); + prj.update_config(|config| { + config.invariant.depth = 15; + config.invariant.fail_on_revert = false; + // Use original counterexample to test sequence len. + config.invariant.shrink_run_limit = 0; + }); + + prj.add_test( + "InvariantSequenceNoReverts.t.sol", + r#" +import "forge-std/Test.sol"; + +contract SequenceNoReverts { + uint256 public count; + + function work(uint256 x) public { + require(x % 2 != 0); + count++; + } +} + +contract SequenceNoRevertsTest is Test { + SequenceNoReverts target; + + function setUp() public { + target = new SequenceNoReverts(); + } + + function invariant_no_reverts() public view { + require(target.count() < 10, "condition met"); + } +} +"#, + ); + + // ensure original counterexample len is 10 (even without shrinking) + cmd.args(["test"]).assert_failure().stdout_eq(str![[r#" +... +Ran 1 test for test/InvariantSequenceNoReverts.t.sol:SequenceNoRevertsTest +[FAIL: condition met] + [Sequence] (original: 10, shrunk: 10) +... + invariant_no_reverts() ([..]) +... +Suite result: FAILED. 0 passed; 1 failed; 0 skipped; [ELAPSED] + +Ran 1 test suite [ELAPSED]: 0 tests passed, 1 failed, 0 skipped (1 total tests) +... +"#]]); +}); + +forgetest_init!( + #[cfg_attr(windows, ignore = "for some reason there's different rng")] + invariant_shrink_big_sequence, + |prj, cmd| { + prj.wipe_contracts(); + prj.update_config(|config| { + config.fuzz.seed = Some(U256::from(119u32)); + config.invariant.runs = 1; + config.invariant.depth = 1000; + }); + + prj.add_test( + "InvariantShrinkBigSequence.t.sol", + r#" +import "forge-std/Test.sol"; + +contract ShrinkBigSequence { + uint256 cond; + + function work(uint256 x) public { + if (x % 2 != 0 && x < 9000) { + cond++; + } + } + + function checkCond() public view { + require(cond < 77, "condition met"); + } +} + +contract ShrinkBigSequenceTest is Test { + ShrinkBigSequence target; + + function setUp() public { + target = new ShrinkBigSequence(); + } + + function invariant_shrink_big_sequence() public view { + target.checkCond(); + } +} +"#, + ); + + // ensure shrinks to same sequence of 77 + cmd.args(["test"]).assert_failure().stdout_eq(str![[r#" +... +Ran 1 test for test/InvariantShrinkBigSequence.t.sol:ShrinkBigSequenceTest +[FAIL: condition met] + [Sequence] (original: [..], shrunk: 77) +... +"#]]); + cmd.assert_failure().stdout_eq(str![[r#" +... +Ran 1 test for test/InvariantShrinkBigSequence.t.sol:ShrinkBigSequenceTest +[FAIL: invariant_shrink_big_sequence replay failure] + [Sequence] (original: [..], shrunk: 77) +... +"#]]); + } +); + +forgetest_init!(invariant_shrink_fail_on_revert, |prj, cmd| { + prj.wipe_contracts(); + prj.update_config(|config| { + config.fuzz.seed = Some(U256::from(119u32)); + config.invariant.fail_on_revert = true; + config.invariant.runs = 1; + config.invariant.depth = 200; + }); + + prj.add_test( + "InvariantShrinkFailOnRevert.t.sol", + r#" +import "forge-std/Test.sol"; + +contract ShrinkFailOnRevert { + uint256 cond; + + function work(uint256 x) public { + if (x % 2 != 0 && x < 9000) { + cond++; + } + require(cond < 10, "condition met"); + } +} + +contract ShrinkFailOnRevertTest is Test { + ShrinkFailOnRevert target; + + function setUp() public { + target = new ShrinkFailOnRevert(); + } + + function invariant_shrink_fail_on_revert() public view {} +} +"#, + ); + + cmd.args(["test"]).assert_failure().stdout_eq(str![[r#" +... +Ran 1 test for test/InvariantShrinkFailOnRevert.t.sol:ShrinkFailOnRevertTest +[FAIL: condition met] + [Sequence] (original: [..], shrunk: 10) +... +"#]]); +}); + +forgetest_init!(invariant_shrink_with_assert, |prj, cmd| { + prj.wipe_contracts(); + prj.update_config(|config| { + config.fuzz.seed = Some(U256::from(100u32)); + config.invariant.runs = 1; + config.invariant.depth = 15; + }); + + prj.add_test( + "InvariantShrinkWithAssert.t.sol", + r#" +import "forge-std/Test.sol"; + +contract Counter { + uint256 public number; + + function increment() public { + number++; + } + + function decrement() public { + number--; + } +} + +contract InvariantShrinkWithAssert is Test { + Counter public counter; + + function setUp() public { + counter = new Counter(); + } + + function invariant_with_assert() public { + assertTrue(counter.number() < 2, "wrong counter assert"); + } + + function invariant_with_require() public { + require(counter.number() < 2, "wrong counter require"); + } +} +"#, + ); + + cmd.args(["test"]).assert_failure().stdout_eq(str![[r#" +... +Ran 2 tests for test/InvariantShrinkWithAssert.t.sol:InvariantShrinkWithAssert +[FAIL: wrong counter assert] + [Sequence] (original: 2, shrunk: 2) +... + invariant_with_assert() ([..]) +... +[FAIL: wrong counter require] + [Sequence] (original: 2, shrunk: 2) +... + invariant_with_require() ([..]) +... +"#]]); +}); + +forgetest_init!(invariant_test1, |prj, cmd| { + prj.wipe_contracts(); + prj.update_config(|config| { + config.invariant.depth = 10; + }); + + prj.add_test( + "InvariantTest1.t.sol", + r#" +import "forge-std/Test.sol"; + +contract InvariantBreaker { + bool public flag0 = true; + bool public flag1 = true; + + function set0(int256 val) public returns (bool) { + if (val % 100 == 0) { + flag0 = false; + } + return flag0; + } + + function set1(int256 val) public returns (bool) { + if (val % 10 == 0 && !flag0) { + flag1 = false; + } + return flag1; + } +} + +contract InvariantTest is Test { + InvariantBreaker inv; + + function setUp() public { + inv = new InvariantBreaker(); + } + + function invariant_neverFalse() public { + require(inv.flag1(), "false"); + } + + function statefulFuzz_neverFalseWithInvariantAlias() public { + require(inv.flag1(), "false"); + } +} +"#, + ); + + assert_invariant(cmd.args(["test"])).failure().stdout_eq(str![[r#" +... +Ran 2 tests for test/InvariantTest1.t.sol:InvariantTest +[FAIL: false] + [SEQUENCE] + invariant_neverFalse() ([RUNS]) + +[STATS] + +[FAIL: false] + [SEQUENCE] + statefulFuzz_neverFalseWithInvariantAlias() ([RUNS]) + +[STATS] + +Suite result: FAILED. 0 passed; 2 failed; 0 skipped; [ELAPSED] + +Ran 1 test suite [ELAPSED]: 0 tests passed, 2 failed, 0 skipped (2 total tests) + +Failing tests: +Encountered 2 failing tests in test/InvariantTest1.t.sol:InvariantTest +[FAIL: false] + [SEQUENCE] + invariant_neverFalse() ([RUNS]) +[FAIL: false] + [SEQUENCE] + statefulFuzz_neverFalseWithInvariantAlias() ([RUNS]) + +Encountered a total of 2 failing tests, 0 tests succeeded + +Tip: Run `forge test --rerun` to retry only the 2 failed tests + +"#]]); +}); diff --git a/crates/forge/tests/it/invariant.rs b/crates/forge/tests/cli/test_cmd/invariant/mod.rs similarity index 54% rename from crates/forge/tests/it/invariant.rs rename to crates/forge/tests/cli/test_cmd/invariant/mod.rs index 83ba8660b4457..4e93f00b404b1 100644 --- a/crates/forge/tests/it/invariant.rs +++ b/crates/forge/tests/cli/test_cmd/invariant/mod.rs @@ -1,700 +1,16 @@ -//! Invariant tests. - -use crate::{config::*, test_helpers::TEST_DATA_DEFAULT}; use alloy_primitives::U256; -use forge::fuzz::CounterExample; -use foundry_test_utils::{Filter, forgetest_init, str}; -use std::collections::BTreeMap; - -macro_rules! get_counterexample { - ($runner:ident, $filter:expr) => { - $runner - .test_collect($filter) - .unwrap() - .values() - .last() - .expect("Invariant contract should be testable.") - .test_results - .values() - .last() - .expect("Invariant contract should be testable.") - .counterexample - .as_ref() - .expect("Invariant contract should have failed with a counterexample.") - }; -} - -#[tokio::test(flavor = "multi_thread")] -async fn test_invariant_with_alias() { - let filter = Filter::new(".*", ".*", ".*fuzz/invariant/common/InvariantTest1.t.sol"); - let results = TEST_DATA_DEFAULT.runner().test_collect(&filter).unwrap(); - assert_multiple( - &results, - BTreeMap::from([( - "default/fuzz/invariant/common/InvariantTest1.t.sol:InvariantTest", - vec![ - ("invariant_neverFalse()", false, Some("false".into()), None, None), - ( - "statefulFuzz_neverFalseWithInvariantAlias()", - false, - Some("false".into()), - None, - None, - ), - ], - )]), - ); -} - -#[tokio::test(flavor = "multi_thread")] -async fn test_invariant_filters() { - let mut runner = TEST_DATA_DEFAULT.runner_with(|config| { - config.invariant.runs = 10; - }); - - // Contracts filter tests. - assert_multiple( - &runner - .test_collect(&Filter::new( - ".*", - ".*", - ".*fuzz/invariant/target/(ExcludeContracts|TargetContracts).t.sol", - )) - .unwrap(), - BTreeMap::from([ - ( - "default/fuzz/invariant/target/ExcludeContracts.t.sol:ExcludeContracts", - vec![("invariantTrueWorld()", true, None, None, None)], - ), - ( - "default/fuzz/invariant/target/TargetContracts.t.sol:TargetContracts", - vec![("invariantTrueWorld()", true, None, None, None)], - ), - ]), - ); - - // Senders filter tests. - assert_multiple( - &runner - .test_collect(&Filter::new( - ".*", - ".*", - ".*fuzz/invariant/target/(ExcludeSenders|TargetSenders).t.sol", - )) - .unwrap(), - BTreeMap::from([ - ( - "default/fuzz/invariant/target/ExcludeSenders.t.sol:ExcludeSenders", - vec![("invariantTrueWorld()", true, None, None, None)], - ), - ( - "default/fuzz/invariant/target/TargetSenders.t.sol:TargetSenders", - vec![("invariantTrueWorld()", false, Some("false world".into()), None, None)], - ), - ]), - ); - - // Interfaces filter tests. - assert_multiple( - &runner - .test_collect(&Filter::new( - ".*", - ".*", - ".*fuzz/invariant/target/TargetInterfaces.t.sol", - )) - .unwrap(), - BTreeMap::from([( - "default/fuzz/invariant/target/TargetInterfaces.t.sol:TargetWorldInterfaces", - vec![("invariantTrueWorld()", false, Some("false world".into()), None, None)], - )]), - ); - - // Selectors filter tests. - assert_multiple( - &runner - .test_collect(&Filter::new( - ".*", - ".*", - ".*fuzz/invariant/target/(ExcludeSelectors|TargetSelectors).t.sol", - )) - .unwrap(), - BTreeMap::from([ - ( - "default/fuzz/invariant/target/ExcludeSelectors.t.sol:ExcludeSelectors", - vec![("invariantFalseWorld()", true, None, None, None)], - ), - ( - "default/fuzz/invariant/target/TargetSelectors.t.sol:TargetSelectors", - vec![("invariantTrueWorld()", true, None, None, None)], - ), - ]), - ); - - // Artifacts filter tests. - assert_multiple( - &runner.test_collect(&Filter::new( - ".*", - ".*", - ".*fuzz/invariant/targetAbi/(ExcludeArtifacts|TargetArtifacts|TargetArtifactSelectors|TargetArtifactSelectors2).t.sol", - )).unwrap(), - BTreeMap::from([ - ( - "default/fuzz/invariant/targetAbi/ExcludeArtifacts.t.sol:ExcludeArtifacts", - vec![("invariantShouldPass()", true, None, None, None)], - ), - ( - "default/fuzz/invariant/targetAbi/TargetArtifacts.t.sol:TargetArtifacts", - vec![ - ("invariantShouldPass()", true, None, None, None), - ( - "invariantShouldFail()", - false, - Some("false world".into()), - None, - None, - ), - ], - ), - ( - "default/fuzz/invariant/targetAbi/TargetArtifactSelectors.t.sol:TargetArtifactSelectors", - vec![("invariantShouldPass()", true, None, None, None)], - ), - ( - "default/fuzz/invariant/targetAbi/TargetArtifactSelectors2.t.sol:TargetArtifactSelectors2", - vec![( - "invariantShouldFail()", - false, - Some("it's false".into()), - None, - None, - )], - ), - ]), - ); -} - -#[tokio::test(flavor = "multi_thread")] -async fn test_invariant_override() { - let filter = Filter::new(".*", ".*", ".*fuzz/invariant/common/InvariantReentrancy.t.sol"); - let mut runner = TEST_DATA_DEFAULT.runner_with(|config| { - config.invariant.fail_on_revert = false; - config.invariant.call_override = true; - }); - let results = runner.test_collect(&filter).unwrap(); - assert_multiple( - &results, - BTreeMap::from([( - "default/fuzz/invariant/common/InvariantReentrancy.t.sol:InvariantReentrancy", - vec![("invariantNotStolen()", false, Some("stolen".into()), None, None)], - )]), - ); -} - -#[tokio::test(flavor = "multi_thread")] -async fn test_invariant_fail_on_revert() { - let filter = Filter::new(".*", ".*", ".*fuzz/invariant/common/InvariantHandlerFailure.t.sol"); - let mut runner = TEST_DATA_DEFAULT.runner_with(|config| { - config.invariant.fail_on_revert = true; - config.invariant.runs = 1; - config.invariant.depth = 10; - }); - let results = runner.test_collect(&filter).unwrap(); - assert_multiple( - &results, - BTreeMap::from([( - "default/fuzz/invariant/common/InvariantHandlerFailure.t.sol:InvariantHandlerFailure", - vec![( - "statefulFuzz_BrokenInvariant()", - false, - Some("failed on revert".into()), - None, - None, - )], - )]), - ); -} - -#[tokio::test(flavor = "multi_thread")] -#[ignore] -async fn test_invariant_storage() { - let filter = Filter::new(".*", ".*", ".*fuzz/invariant/storage/InvariantStorageTest.t.sol"); - let mut runner = TEST_DATA_DEFAULT.runner_with(|config| { - config.invariant.depth = 100; - if cfg!(windows) { - config.invariant.depth += 50; - } - config.fuzz.seed = Some(U256::from(6u32)); - }); - let results = runner.test_collect(&filter).unwrap(); - assert_multiple( - &results, - BTreeMap::from([( - "default/fuzz/invariant/storage/InvariantStorageTest.t.sol:InvariantStorageTest", - vec![ - ("invariantChangeAddress()", false, Some("changedAddr".to_string()), None, None), - ("invariantChangeString()", false, Some("changedString".to_string()), None, None), - ("invariantChangeUint()", false, Some("changedUint".to_string()), None, None), - ("invariantPush()", false, Some("pushUint".to_string()), None, None), - ], - )]), - ); -} - -#[tokio::test(flavor = "multi_thread")] -async fn test_invariant_inner_contract() { - let filter = Filter::new(".*", ".*", ".*fuzz/invariant/common/InvariantInnerContract.t.sol"); - let results = TEST_DATA_DEFAULT.runner().test_collect(&filter).unwrap(); - assert_multiple( - &results, - BTreeMap::from([( - "default/fuzz/invariant/common/InvariantInnerContract.t.sol:InvariantInnerContract", - vec![("invariantHideJesus()", false, Some("jesus betrayed".into()), None, None)], - )]), - ); -} - -#[tokio::test(flavor = "multi_thread")] -#[cfg_attr(windows, ignore = "for some reason there's different rng")] -async fn test_invariant_shrink() { - let filter = Filter::new(".*", ".*", ".*fuzz/invariant/common/InvariantInnerContract.t.sol"); - let mut runner = - TEST_DATA_DEFAULT.runner_with(|config| config.fuzz.seed = Some(U256::from(119u32))); - - match get_counterexample!(runner, &filter) { - CounterExample::Single(_) => panic!("CounterExample should be a sequence."), - // `fuzz_seed` at 119 makes this sequence shrinkable from 4 to 2. - CounterExample::Sequence(_, sequence) => { - assert!(sequence.len() <= 3); - - if sequence.len() == 2 { - // call order should always be preserved - let create_fren_sequence = sequence[0].clone(); - assert_eq!( - create_fren_sequence.contract_name.unwrap(), - "default/fuzz/invariant/common/InvariantInnerContract.t.sol:Jesus" - ); - assert_eq!(create_fren_sequence.signature.unwrap(), "create_fren()"); - - let betray_sequence = sequence[1].clone(); - assert_eq!( - betray_sequence.contract_name.unwrap(), - "default/fuzz/invariant/common/InvariantInnerContract.t.sol:Judas" - ); - assert_eq!(betray_sequence.signature.unwrap(), "betray()"); - } - } - }; -} - -#[tokio::test(flavor = "multi_thread")] -#[cfg_attr(windows, ignore = "for some reason there's different rng")] -async fn test_invariant_assert_shrink() { - // ensure assert shrinks to same sequence of 2 as require - check_shrink_sequence("invariant_with_assert", 2).await; -} - -#[tokio::test(flavor = "multi_thread")] -#[cfg_attr(windows, ignore = "for some reason there's different rng")] -async fn test_invariant_require_shrink() { - // ensure require shrinks to same sequence of 2 as assert - check_shrink_sequence("invariant_with_require", 2).await; -} - -async fn check_shrink_sequence(test_pattern: &str, expected_len: usize) { - let filter = - Filter::new(test_pattern, ".*", ".*fuzz/invariant/common/InvariantShrinkWithAssert.t.sol"); - let mut runner = TEST_DATA_DEFAULT.runner_with(|config| { - config.fuzz.seed = Some(U256::from(100u32)); - config.invariant.runs = 1; - config.invariant.depth = 15; - }); - - match get_counterexample!(runner, &filter) { - CounterExample::Single(_) => panic!("CounterExample should be a sequence."), - CounterExample::Sequence(_, sequence) => { - assert_eq!(sequence.len(), expected_len); - } - }; -} - -#[tokio::test(flavor = "multi_thread")] -#[cfg_attr(windows, ignore = "for some reason there's different rng")] -async fn test_shrink_big_sequence() { - let filter = - Filter::new(".*", ".*", ".*fuzz/invariant/common/InvariantShrinkBigSequence.t.sol"); - let mut runner = TEST_DATA_DEFAULT.runner_with(|config| { - config.fuzz.seed = Some(U256::from(119u32)); - config.invariant.runs = 1; - config.invariant.depth = 1000; - }); - - let initial_counterexample = runner - .test_collect(&filter) - .unwrap() - .values() - .last() - .expect("Invariant contract should be testable.") - .test_results - .values() - .last() - .expect("Invariant contract should be testable.") - .counterexample - .clone() - .unwrap(); - - let initial_sequence = match initial_counterexample { - CounterExample::Single(_) => panic!("CounterExample should be a sequence."), - CounterExample::Sequence(_, sequence) => sequence, - }; - // ensure shrinks to same sequence of 77 - assert_eq!(initial_sequence.len(), 77); - - // test failure persistence - let results = runner.test_collect(&filter).unwrap(); - assert_multiple( - &results, - BTreeMap::from([( - "default/fuzz/invariant/common/InvariantShrinkBigSequence.t.sol:ShrinkBigSequenceTest", - vec![( - "invariant_shrink_big_sequence()", - false, - Some("invariant_shrink_big_sequence replay failure".into()), - None, - None, - )], - )]), - ); - let new_sequence = match results - .values() - .last() - .expect("Invariant contract should be testable.") - .test_results - .values() - .last() - .expect("Invariant contract should be testable.") - .counterexample - .clone() - .unwrap() - { - CounterExample::Single(_) => panic!("CounterExample should be a sequence."), - CounterExample::Sequence(_, sequence) => sequence, - }; - // ensure shrinks to same sequence of 77 - assert_eq!(new_sequence.len(), 77); - // ensure calls within failed sequence are the same as initial one - for index in 0..77 { - let new_call = new_sequence.get(index).unwrap(); - let initial_call = initial_sequence.get(index).unwrap(); - assert_eq!(new_call.sender, initial_call.sender); - assert_eq!(new_call.addr, initial_call.addr); - assert_eq!(new_call.calldata, initial_call.calldata); - } -} - -#[tokio::test(flavor = "multi_thread")] -#[cfg_attr(windows, ignore = "for some reason there's different rng")] -async fn test_shrink_fail_on_revert() { - let filter = - Filter::new(".*", ".*", ".*fuzz/invariant/common/InvariantShrinkFailOnRevert.t.sol"); - let mut runner = TEST_DATA_DEFAULT.runner_with(|config| { - config.fuzz.seed = Some(U256::from(119u32)); - config.invariant.fail_on_revert = true; - config.invariant.runs = 1; - config.invariant.depth = 200; - }); - - match get_counterexample!(runner, &filter) { - CounterExample::Single(_) => panic!("CounterExample should be a sequence."), - CounterExample::Sequence(_, sequence) => { - // ensure shrinks to sequence of 10 - assert_eq!(sequence.len(), 10); - } - }; -} - -#[tokio::test(flavor = "multi_thread")] -async fn test_invariant_preserve_state() { - let filter = Filter::new(".*", ".*", ".*fuzz/invariant/common/InvariantPreserveState.t.sol"); - let mut runner = TEST_DATA_DEFAULT.runner_with(|config| { - config.invariant.fail_on_revert = true; - }); - let results = runner.test_collect(&filter).unwrap(); - assert_multiple( - &results, - BTreeMap::from([( - "default/fuzz/invariant/common/InvariantPreserveState.t.sol:InvariantPreserveState", - vec![( - "invariant_preserve_state()", - false, - Some("EvmError: Revert".into()), - None, - None, - )], - )]), - ); -} - -#[tokio::test(flavor = "multi_thread")] -async fn test_invariant_with_address_fixture() { - let mut runner = TEST_DATA_DEFAULT.runner(); - let results = runner - .test_collect(&Filter::new( - ".*", - ".*", - ".*fuzz/invariant/common/InvariantCalldataDictionary.t.sol", - )) - .unwrap(); - assert_multiple( - &results, - BTreeMap::from([( - "default/fuzz/invariant/common/InvariantCalldataDictionary.t.sol:InvariantCalldataDictionary", - vec![( - "invariant_owner_never_changes()", - false, - Some("".into()), - None, - None, - )], - )]), - ); -} - -#[tokio::test(flavor = "multi_thread")] -async fn test_invariant_assume_does_not_revert() { - let filter = Filter::new(".*", ".*", ".*fuzz/invariant/common/InvariantAssume.t.sol"); - let mut runner = TEST_DATA_DEFAULT.runner_with(|config| { - // Should not treat vm.assume as revert. - config.invariant.fail_on_revert = true; - }); - let results = runner.test_collect(&filter).unwrap(); - assert_multiple( - &results, - BTreeMap::from([( - "default/fuzz/invariant/common/InvariantAssume.t.sol:InvariantAssume", - vec![("invariant_dummy()", true, None, None, None)], - )]), - ); -} - -#[tokio::test(flavor = "multi_thread")] -async fn test_invariant_assume_respects_restrictions() { - let filter = Filter::new(".*", ".*", ".*fuzz/invariant/common/InvariantAssume.t.sol"); - let mut runner = TEST_DATA_DEFAULT.runner_with(|config| { - config.invariant.runs = 1; - config.invariant.depth = 10; - config.invariant.max_assume_rejects = 1; - }); - let results = runner.test_collect(&filter).unwrap(); - assert_multiple( - &results, - BTreeMap::from([( - "default/fuzz/invariant/common/InvariantAssume.t.sol:InvariantAssume", - vec![( - "invariant_dummy()", - false, - Some("`vm.assume` rejected too many inputs (1 allowed)".into()), - None, - None, - )], - )]), - ); -} - -#[tokio::test(flavor = "multi_thread")] -async fn test_invariant_decode_custom_error() { - let filter = Filter::new(".*", ".*", ".*fuzz/invariant/common/InvariantCustomError.t.sol"); - let mut runner = TEST_DATA_DEFAULT.runner_with(|config| { - config.invariant.fail_on_revert = true; - }); - let results = runner.test_collect(&filter).unwrap(); - assert_multiple( - &results, - BTreeMap::from([( - "default/fuzz/invariant/common/InvariantCustomError.t.sol:InvariantCustomError", - vec![( - "invariant_decode_error()", - false, - Some("InvariantCustomError(111, \"custom\")".into()), - None, - None, - )], - )]), - ); -} - -#[tokio::test(flavor = "multi_thread")] -async fn test_invariant_fuzzed_selected_targets() { - let filter = Filter::new(".*", ".*", ".*fuzz/invariant/target/FuzzedTargetContracts.t.sol"); - let mut runner = TEST_DATA_DEFAULT.runner_with(|config| { - config.invariant.fail_on_revert = true; - }); - let results = runner.test_collect(&filter).unwrap(); - assert_multiple( - &results, - BTreeMap::from([ - ( - "default/fuzz/invariant/target/FuzzedTargetContracts.t.sol:ExplicitTargetContract", - vec![("invariant_explicit_target()", true, None, None, None)], - ), - ( - "default/fuzz/invariant/target/FuzzedTargetContracts.t.sol:DynamicTargetContract", - vec![( - "invariant_dynamic_targets()", - false, - Some("wrong target selector called".into()), - None, - None, - )], - ), - ]), - ); -} - -#[tokio::test(flavor = "multi_thread")] -async fn test_invariant_fixtures() { - let filter = Filter::new(".*", ".*", ".*fuzz/invariant/common/InvariantFixtures.t.sol"); - let mut runner = TEST_DATA_DEFAULT.runner_with(|config| { - config.invariant.runs = 1; - config.invariant.depth = 100; - }); - let results = runner.test_collect(&filter).unwrap(); - assert_multiple( - &results, - BTreeMap::from([( - "default/fuzz/invariant/common/InvariantFixtures.t.sol:InvariantFixtures", - vec![( - "invariant_target_not_compromised()", - false, - Some("".into()), - None, - None, - )], - )]), - ); -} - -#[tokio::test(flavor = "multi_thread")] -async fn test_invariant_scrape_values() { - let filter = Filter::new(".*", ".*", ".*fuzz/invariant/common/InvariantScrapeValues.t.sol"); - let results = TEST_DATA_DEFAULT.runner().test_collect(&filter).unwrap(); - assert_multiple( - &results, - BTreeMap::from([ - ( - "default/fuzz/invariant/common/InvariantScrapeValues.t.sol:FindFromReturnValueTest", - vec![( - "invariant_value_not_found()", - false, - Some("value from return found".into()), - None, - None, - )], - ), - ( - "default/fuzz/invariant/common/InvariantScrapeValues.t.sol:FindFromLogValueTest", - vec![( - "invariant_value_not_found()", - false, - Some("value from logs found".into()), - None, - None, - )], - ), - ]), - ); -} - -#[tokio::test(flavor = "multi_thread")] -async fn test_invariant_roll_fork_handler() { - let filter = Filter::new(".*", ".*", ".*fuzz/invariant/common/InvariantRollFork.t.sol"); - let mut runner = TEST_DATA_DEFAULT.runner_with(|config| { - config.fuzz.seed = Some(U256::from(119u32)); - }); - let results = runner.test_collect(&filter).unwrap(); - assert_multiple( - &results, - BTreeMap::from([ - ( - "default/fuzz/invariant/common/InvariantRollFork.t.sol:InvariantRollForkBlockTest", - vec![( - "invariant_fork_handler_block()", - false, - Some("too many blocks mined".into()), - None, - None, - )], - ), - ( - "default/fuzz/invariant/common/InvariantRollFork.t.sol:InvariantRollForkStateTest", - vec![( - "invariant_fork_handler_state()", - false, - Some("wrong supply".into()), - None, - None, - )], - ), - ]), - ); -} - -#[tokio::test(flavor = "multi_thread")] -async fn test_invariant_excluded_senders() { - let filter = Filter::new(".*", ".*", ".*fuzz/invariant/common/InvariantExcludedSenders.t.sol"); - let mut runner = TEST_DATA_DEFAULT.runner_with(|config| { - config.invariant.fail_on_revert = true; - }); - let results = runner.test_collect(&filter).unwrap(); - assert_multiple( - &results, - BTreeMap::from([( - "default/fuzz/invariant/common/InvariantExcludedSenders.t.sol:InvariantExcludedSendersTest", - vec![("invariant_check_sender()", true, None, None, None)], - )]), - ); -} - -#[tokio::test(flavor = "multi_thread")] -async fn test_invariant_after_invariant() { - // Check failure on passing invariant and failed `afterInvariant` condition - let filter = Filter::new(".*", ".*", ".*fuzz/invariant/common/InvariantAfterInvariant.t.sol"); - let results = TEST_DATA_DEFAULT.runner().test_collect(&filter).unwrap(); - assert_multiple( - &results, - BTreeMap::from([( - "default/fuzz/invariant/common/InvariantAfterInvariant.t.sol:InvariantAfterInvariantTest", - vec![ - ( - "invariant_after_invariant_failure()", - false, - Some("afterInvariant failure".into()), - None, - None, - ), - ("invariant_failure()", false, Some("invariant failure".into()), None, None), - ("invariant_success()", true, None, None, None), - ], - )]), - ); -} - -#[tokio::test(flavor = "multi_thread")] -async fn test_no_reverts_in_counterexample() { - let filter = - Filter::new(".*", ".*", ".*fuzz/invariant/common/InvariantSequenceNoReverts.t.sol"); - let mut runner = TEST_DATA_DEFAULT.runner_with(|config| { - config.invariant.fail_on_revert = false; - // Use original counterexample to test sequence len. - config.invariant.shrink_run_limit = 0; - }); - - match get_counterexample!(runner, &filter) { - CounterExample::Single(_) => panic!("CounterExample should be a sequence."), - CounterExample::Sequence(_, sequence) => { - // ensure original counterexample len is 10 (even without shrinking) - assert_eq!(sequence.len(), 10); - } - }; +use foundry_test_utils::{TestCommand, forgetest_init, snapbox::cmd::OutputAssert, str}; + +mod common; +mod storage; +mod target; + +fn assert_invariant(cmd: &mut TestCommand) -> OutputAssert { + cmd.assert_with(&[ + ("[RUNS]", r"runs: \d+, calls: \d+, reverts: \d+"), + ("[SEQUENCE]", r"\[Sequence\].*(\n\t\t.*)*"), + ("[STATS]", r"╭[\s\S]*?╰.*"), + ]) } // Tests that a persisted failure doesn't fail due to assume revert if test driver is changed. diff --git a/testdata/default/fuzz/invariant/storage/InvariantStorageTest.t.sol b/crates/forge/tests/cli/test_cmd/invariant/storage.rs similarity index 79% rename from testdata/default/fuzz/invariant/storage/InvariantStorageTest.t.sol rename to crates/forge/tests/cli/test_cmd/invariant/storage.rs index 890c495c310bb..83c4f72bca93d 100644 --- a/testdata/default/fuzz/invariant/storage/InvariantStorageTest.t.sol +++ b/crates/forge/tests/cli/test_cmd/invariant/storage.rs @@ -1,6 +1,13 @@ -pragma solidity >0.8.13; +use super::*; -import "ds-test/test.sol"; +forgetest_init!( + #[ignore = "slow"] + storage, + |prj, cmd| { + prj.add_test( + "name", + r#" +import "forge-std/Test.sol"; contract Contract { address public addr = address(0xbeef); @@ -33,7 +40,7 @@ contract Contract { } } -contract InvariantStorageTest is DSTest { +contract InvariantStorageTest is Test { Contract c; function setUp() public { @@ -56,3 +63,9 @@ contract InvariantStorageTest is DSTest { require(c.pushNum() == 0, "pushUint"); } } +"#, + ); + + assert_invariant(cmd.args(["test"])).failure().stdout_eq(str![[r#""#]]); + } +); diff --git a/crates/forge/tests/cli/test_cmd/invariant/target.rs b/crates/forge/tests/cli/test_cmd/invariant/target.rs new file mode 100644 index 0000000000000..31e684d4f307d --- /dev/null +++ b/crates/forge/tests/cli/test_cmd/invariant/target.rs @@ -0,0 +1,766 @@ +use super::*; + +forgetest!(filters, |prj, cmd| { + prj.insert_vm(); + prj.insert_ds_test(); + prj.update_config(|config| { + config.invariant.runs = 50; + config.invariant.depth = 10; + }); + + prj.add_test( + "ExcludeContracts.t.sol", + r#" +import { DSTest as Test } from "src/test.sol"; + +contract Hello { + bool public world = true; + + function change() public { + world = false; + } +} + +contract ExcludeContracts is Test { + Hello hello; + + function setUp() public { + hello = new Hello(); + new Hello(); + } + + function excludeContracts() public view returns (address[] memory) { + address[] memory addrs = new address[](1); + addrs[0] = address(hello); + return addrs; + } + + function invariantTrueWorld() public { + require(hello.world() == true, "false world"); + } +} +"#, + ); + + prj.add_test( + "ExcludeSelectors.t.sol", + r#" +import { DSTest as Test } from "src/test.sol"; + +struct FuzzSelector { + address addr; + bytes4[] selectors; +} + +contract Hello { + bool public world = false; + + function change() public { + world = true; + } + + function real_change() public { + world = false; + } +} + +contract ExcludeSelectors is Test { + Hello hello; + + function setUp() public { + hello = new Hello(); + } + + function excludeSelectors() public view returns (FuzzSelector[] memory) { + FuzzSelector[] memory targets = new FuzzSelector[](1); + bytes4[] memory selectors = new bytes4[](1); + selectors[0] = Hello.change.selector; + targets[0] = FuzzSelector(address(hello), selectors); + return targets; + } + + function invariantFalseWorld() public { + require(hello.world() == false, "true world"); + } +} +"#, + ); + + prj.add_test( + "ExcludeSenders.t.sol", + r#" +import { DSTest as Test } from "src/test.sol"; + +contract Hello { + address seed_address = address(0xdeadbeef); + bool public world = true; + + function changeBeef() public { + require(msg.sender == address(0xdeadbeef)); + world = false; + } + + // address(0) should be automatically excluded + function change0() public { + require(msg.sender == address(0)); + world = false; + } +} + +contract ExcludeSenders is Test { + Hello hello; + + function setUp() public { + hello = new Hello(); + } + + function excludeSenders() public view returns (address[] memory) { + address[] memory addrs = new address[](1); + addrs[0] = address(0xdeadbeef); + return addrs; + } + + // Tests clashing. Exclusion takes priority. + function targetSenders() public view returns (address[] memory) { + address[] memory addrs = new address[](1); + addrs[0] = address(0xdeadbeef); + return addrs; + } + + function invariantTrueWorld() public { + require(hello.world() == true, "false world"); + } +} +"#, + ); + + prj.add_test( + "TargetContracts.t.sol", + r#" +import { DSTest as Test } from "src/test.sol"; + +contract Hello { + bool public world = true; + + function change() public { + world = false; + } +} + +contract TargetContracts is Test { + Hello hello1; + Hello hello2; + + function setUp() public { + hello1 = new Hello(); + hello2 = new Hello(); + } + + function targetContracts() public view returns (address[] memory) { + address[] memory addrs = new address[](1); + addrs[0] = address(hello1); + return addrs; + } + + function invariantTrueWorld() public { + require(hello2.world() == true, "false world"); + } +} +"#, + ); + + prj.add_test( + "TargetInterfaces.t.sol", + r#" +import { DSTest as Test } from "src/test.sol"; + +struct FuzzInterface { + address target; + string[] artifacts; +} + +contract Hello { + bool public world; + + function changeWorld() external { + world = true; + } +} + +interface IHello { + function world() external view returns (bool); + function changeWorld() external; +} + +contract HelloProxy { + address internal immutable _implementation; + + constructor(address implementation_) { + _implementation = implementation_; + } + + function _delegate(address implementation) internal { + assembly { + calldatacopy(0, 0, calldatasize()) + + let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0) + + returndatacopy(0, 0, returndatasize()) + + switch result + case 0 { revert(0, returndatasize()) } + default { return(0, returndatasize()) } + } + } + + fallback() external payable { + _delegate(_implementation); + } +} + +contract TargetWorldInterfaces is Test { + IHello proxy; + + function setUp() public { + Hello hello = new Hello(); + proxy = IHello(address(new HelloProxy(address(hello)))); + } + + function targetInterfaces() public view returns (FuzzInterface[] memory) { + FuzzInterface[] memory targets = new FuzzInterface[](1); + + string[] memory artifacts = new string[](1); + artifacts[0] = "IHello"; + + targets[0] = FuzzInterface(address(proxy), artifacts); + + return targets; + } + + function invariantTrueWorld() public { + require(proxy.world() == false, "false world"); + } +} +"#, + ); + + prj.add_test( + "TargetSelectors.t.sol", + r#" +import { DSTest as Test } from "src/test.sol"; + +struct FuzzSelector { + address addr; + bytes4[] selectors; +} + +contract Hello { + bool public world = true; + + function change() public { + world = true; + } + + function real_change() public { + world = false; + } +} + +contract TargetSelectors is Test { + Hello hello; + + function setUp() public { + hello = new Hello(); + } + + function targetSelectors() public view returns (FuzzSelector[] memory) { + FuzzSelector[] memory targets = new FuzzSelector[](1); + bytes4[] memory selectors = new bytes4[](1); + selectors[0] = Hello.change.selector; + targets[0] = FuzzSelector(address(hello), selectors); + return targets; + } + + function invariantTrueWorld() public { + require(hello.world() == true, "false world"); + } +} +"#, + ); + + prj.add_test( + "TargetSenders.t.sol", + r#" +import { DSTest as Test } from "src/test.sol"; + +contract Hello { + bool public world = true; + + function change() public { + require(msg.sender == address(0xdeadbeef)); + world = false; + } +} + +contract TargetSenders is Test { + Hello hello; + + function setUp() public { + hello = new Hello(); + } + + function targetSenders() public view returns (address[] memory) { + address[] memory addrs = new address[](1); + addrs[0] = address(0xdeadbeef); + return addrs; + } + + function invariantTrueWorld() public { + require(hello.world() == true, "false world"); + } +} +"#, + ); + + prj.add_test( + "ExcludeArtifacts.t.sol", + r#" +import { DSTest as Test } from "src/test.sol"; + +// Will get automatically excluded. Otherwise it would throw error. +contract NoMutFunctions { + function no_change() public pure {} +} + +contract Excluded { + bool public world = true; + + function change() public { + world = false; + } +} + +contract Hello { + bool public world = true; + + function change() public { + world = false; + } +} + +contract ExcludeArtifacts is Test { + Excluded excluded; + + function setUp() public { + excluded = new Excluded(); + new Hello(); + new NoMutFunctions(); + } + + function excludeArtifacts() public returns (string[] memory) { + string[] memory abis = new string[](1); + abis[0] = "test/ExcludeArtifacts.t.sol:Excluded"; + return abis; + } + + function invariantShouldPass() public { + require(excluded.world() == true, "false world"); + } +} +"#, + ); + + prj.add_test( + "TargetArtifactSelectors2.t.sol", + r#" +import { DSTest as Test } from "src/test.sol"; + +struct FuzzArtifactSelector { + string artifact; + bytes4[] selectors; +} + +contract Parent { + bool public should_be_true = true; + address public child; + + function change() public { + child = msg.sender; + should_be_true = false; + } + + function create() public { + new Child(); + } +} + +contract Child { + Parent parent; + bool public changed = false; + + constructor() { + parent = Parent(msg.sender); + } + + function change_parent() public { + parent.change(); + } + + function tracked_change_parent() public { + parent.change(); + } +} + +contract TargetArtifactSelectors2 is Test { + Parent parent; + + function setUp() public { + parent = new Parent(); + } + + function targetArtifactSelectors() public returns (FuzzArtifactSelector[] memory) { + FuzzArtifactSelector[] memory targets = new FuzzArtifactSelector[](2); + bytes4[] memory selectors_child = new bytes4[](1); + + selectors_child[0] = Child.change_parent.selector; + targets[0] = FuzzArtifactSelector( + "test/TargetArtifactSelectors2.t.sol:Child", selectors_child + ); + + bytes4[] memory selectors_parent = new bytes4[](1); + selectors_parent[0] = Parent.create.selector; + targets[1] = FuzzArtifactSelector( + "test/TargetArtifactSelectors2.t.sol:Parent", selectors_parent + ); + return targets; + } + + function invariantShouldFail() public { + if (!parent.should_be_true()) { + require(!Child(address(parent.child())).changed(), "should have not happened"); + } + require(parent.should_be_true() == true, "it's false"); + } +} +"#, + ); + + prj.add_test( + "TargetArtifactSelectors.t.sol", + r#" +import { DSTest as Test } from "src/test.sol"; + +struct FuzzArtifactSelector { + string artifact; + bytes4[] selectors; +} + +contract Hi { + bool public world = true; + + function no_change() public { + world = true; + } + + function change() public { + world = false; + } +} + +contract TargetArtifactSelectors is Test { + Hi hello; + + function setUp() public { + hello = new Hi(); + } + + function targetArtifactSelectors() public returns (FuzzArtifactSelector[] memory) { + FuzzArtifactSelector[] memory targets = new FuzzArtifactSelector[](1); + bytes4[] memory selectors = new bytes4[](1); + selectors[0] = Hi.no_change.selector; + targets[0] = + FuzzArtifactSelector("test/TargetArtifactSelectors.t.sol:Hi", selectors); + return targets; + } + + function invariantShouldPass() public { + require(hello.world() == true, "false world"); + } +} +"#, + ); + + prj.add_test( + "TargetArtifacts.t.sol", + r#" +import { DSTest as Test } from "src/test.sol"; + +contract Targeted { + bool public world = true; + + function change() public { + world = false; + } +} + +contract Hello { + bool public world = true; + + function no_change() public {} +} + +contract TargetArtifacts is Test { + Targeted target1; + Targeted target2; + Hello hello; + + function setUp() public { + target1 = new Targeted(); + target2 = new Targeted(); + hello = new Hello(); + } + + function targetArtifacts() public returns (string[] memory) { + string[] memory abis = new string[](1); + abis[0] = "test/TargetArtifacts.t.sol:Targeted"; + return abis; + } + + function invariantShouldPass() public { + require(target2.world() == true || target1.world() == true || hello.world() == true, "false world"); + } + + function invariantShouldFail() public { + require(target2.world() == true || target1.world() == true, "false world"); + } +} +"#, + ); + + assert_invariant(cmd.args(["test", "-j1"])).failure().stdout_eq(str![[r#" +... +Ran 1 test for test/ExcludeArtifacts.t.sol:ExcludeArtifacts +[PASS] invariantShouldPass() ([RUNS]) + +[STATS] + +Suite result: ok. 1 passed; 0 failed; 0 skipped; [ELAPSED] + +Ran 1 test for test/ExcludeContracts.t.sol:ExcludeContracts +[PASS] invariantTrueWorld() ([RUNS]) + +[STATS] + +Suite result: ok. 1 passed; 0 failed; 0 skipped; [ELAPSED] + +Ran 1 test for test/ExcludeSelectors.t.sol:ExcludeSelectors +[PASS] invariantFalseWorld() ([RUNS]) + +[STATS] + +Suite result: ok. 1 passed; 0 failed; 0 skipped; [ELAPSED] + +Ran 1 test for test/ExcludeSenders.t.sol:ExcludeSenders +[PASS] invariantTrueWorld() ([RUNS]) + +[STATS] + +Suite result: ok. 1 passed; 0 failed; 0 skipped; [ELAPSED] + +Ran 1 test for test/TargetArtifactSelectors.t.sol:TargetArtifactSelectors +[PASS] invariantShouldPass() ([RUNS]) + +[STATS] + +Suite result: ok. 1 passed; 0 failed; 0 skipped; [ELAPSED] + +Ran 1 test for test/TargetArtifactSelectors2.t.sol:TargetArtifactSelectors2 +[FAIL: it's false] + [SEQUENCE] + invariantShouldFail() ([RUNS]) + +[STATS] + +Suite result: FAILED. 0 passed; 1 failed; 0 skipped; [ELAPSED] + +Ran 2 tests for test/TargetArtifacts.t.sol:TargetArtifacts +[FAIL: false world] + [SEQUENCE] + invariantShouldFail() ([RUNS]) + +[STATS] + +[PASS] invariantShouldPass() ([RUNS]) + +[STATS] + +Suite result: FAILED. 1 passed; 1 failed; 0 skipped; [ELAPSED] + +Ran 1 test for test/TargetContracts.t.sol:TargetContracts +[PASS] invariantTrueWorld() ([RUNS]) + +[STATS] + +Suite result: ok. 1 passed; 0 failed; 0 skipped; [ELAPSED] + +Ran 1 test for test/TargetInterfaces.t.sol:TargetWorldInterfaces +[FAIL: false world] + [SEQUENCE] + invariantTrueWorld() ([RUNS]) + +[STATS] + +Suite result: FAILED. 0 passed; 1 failed; 0 skipped; [ELAPSED] + +Ran 1 test for test/TargetSelectors.t.sol:TargetSelectors +[PASS] invariantTrueWorld() ([RUNS]) + +[STATS] + +Suite result: ok. 1 passed; 0 failed; 0 skipped; [ELAPSED] + +Ran 1 test for test/TargetSenders.t.sol:TargetSenders +[FAIL: false world] + [SEQUENCE] + invariantTrueWorld() ([RUNS]) + +[STATS] + +Suite result: FAILED. 0 passed; 1 failed; 0 skipped; [ELAPSED] + +Ran 11 test suites [ELAPSED]: 8 tests passed, 4 failed, 0 skipped (12 total tests) + +Failing tests: +Encountered 1 failing test in test/TargetArtifactSelectors2.t.sol:TargetArtifactSelectors2 +[FAIL: it's false] + [SEQUENCE] + invariantShouldFail() ([RUNS]) + +Encountered 1 failing test in test/TargetArtifacts.t.sol:TargetArtifacts +[FAIL: false world] + [SEQUENCE] + invariantShouldFail() ([RUNS]) + +Encountered 1 failing test in test/TargetInterfaces.t.sol:TargetWorldInterfaces +[FAIL: false world] + [SEQUENCE] + invariantTrueWorld() ([RUNS]) + +Encountered 1 failing test in test/TargetSenders.t.sol:TargetSenders +[FAIL: false world] + [SEQUENCE] + invariantTrueWorld() ([RUNS]) + +Encountered a total of 4 failing tests, 8 tests succeeded + +Tip: Run `forge test --rerun` to retry only the 4 failed tests + +"#]]); +}); + +// https://github.com/foundry-rs/foundry/issues/5625 +// https://github.com/foundry-rs/foundry/issues/6166 +// `Target.wrongSelector` is not called when handler added as `targetContract` +// `Target.wrongSelector` is called (and test fails) when no `targetContract` set +forgetest!(fuzzed_selected_targets, |prj, cmd| { + prj.insert_vm(); + prj.insert_ds_test(); + prj.update_config(|config| { + config.invariant.depth = 10; + config.invariant.fail_on_revert = true; + }); + + prj.add_test( + "FuzzedTargetContracts.t.sol", + r#" +import { DSTest as Test } from "src/test.sol"; +import "src/Vm.sol"; + +contract Target { + uint256 count; + + function wrongSelector() external { + revert("wrong target selector called"); + } + + function goodSelector() external { + count++; + } +} + +contract Handler is Test { + function increment() public { + Target(0x6B175474E89094C44Da98b954EedeAC495271d0F).goodSelector(); + } +} + +contract ExplicitTargetContract is Test { + Vm constant vm = Vm(HEVM_ADDRESS); + Handler handler; + + function setUp() public { + Target target = new Target(); + bytes memory targetCode = address(target).code; + vm.etch(address(0x6B175474E89094C44Da98b954EedeAC495271d0F), targetCode); + + handler = new Handler(); + } + + function targetContracts() public view returns (address[] memory) { + address[] memory addrs = new address[](1); + addrs[0] = address(handler); + return addrs; + } + + function invariant_explicit_target() public {} +} + +contract DynamicTargetContract is Test { + Vm constant vm = Vm(HEVM_ADDRESS); + Handler handler; + + function setUp() public { + Target target = new Target(); + bytes memory targetCode = address(target).code; + vm.etch(address(0x6B175474E89094C44Da98b954EedeAC495271d0F), targetCode); + + handler = new Handler(); + } + + function invariant_dynamic_targets() public {} +} +"#, + ); + + assert_invariant(cmd.args(["test", "-j1"])).failure().stdout_eq(str![[r#" +... +Ran 1 test for test/FuzzedTargetContracts.t.sol:DynamicTargetContract +[FAIL: wrong target selector called] + [SEQUENCE] + invariant_dynamic_targets() ([RUNS]) + +[STATS] + +Suite result: FAILED. 0 passed; 1 failed; 0 skipped; [ELAPSED] + +Ran 1 test for test/FuzzedTargetContracts.t.sol:ExplicitTargetContract +[PASS] invariant_explicit_target() ([RUNS]) + +[STATS] + +Suite result: ok. 1 passed; 0 failed; 0 skipped; [ELAPSED] + +Ran 2 test suites [ELAPSED]: 1 tests passed, 1 failed, 0 skipped (2 total tests) + +Failing tests: +Encountered 1 failing test in test/FuzzedTargetContracts.t.sol:DynamicTargetContract +[FAIL: wrong target selector called] + [SEQUENCE] + invariant_dynamic_targets() ([RUNS]) + +Encountered a total of 1 failing tests, 1 tests succeeded + +Tip: Run `forge test --rerun` to retry only the 1 failed test + +"#]]); +}); diff --git a/crates/forge/tests/cli/test_cmd/logs.rs b/crates/forge/tests/cli/test_cmd/logs.rs new file mode 100644 index 0000000000000..7aeafc2065ac8 --- /dev/null +++ b/crates/forge/tests/cli/test_cmd/logs.rs @@ -0,0 +1,756 @@ +//! Tests for various logging functionality + +use foundry_test_utils::str; + +forgetest_init!(debug_logs, |prj, cmd| { + prj.wipe_contracts(); + prj.add_test( + "DebugLogs.t.sol", + r#" +import "forge-std/Test.sol"; + +contract DebugLogsTest is Test { + constructor() { + emit log_uint(0); + } + + function setUp() public { + emit log_uint(1); + } + + function test1() public { + emit log_uint(2); + } + + function test2() public { + emit log_uint(3); + } + + function testRevertIfWithRevert() public { + Fails fails = new Fails(); + emit log_uint(4); + vm.expectRevert(); + fails.failure(); + } + + /// forge-config: default.allow_internal_expect_revert = true + function testRevertIfWithRequire() public { + emit log_uint(5); + vm.expectRevert(); + require(false); + } + + function testLog() public { + emit log("Error: Assertion Failed"); + } + + function testLogs() public { + emit logs(bytes("abcd")); + } + + function testLogAddress() public { + emit log_address(address(1)); + } + + function testLogBytes32() public { + emit log_bytes32(bytes32("abcd")); + } + + function testLogInt() public { + emit log_int(int256(-31337)); + } + + function testLogBytes() public { + emit log_bytes(bytes("abcd")); + } + + function testLogString() public { + emit log_string("here"); + } + + function testLogNamedAddress() public { + emit log_named_address("address", address(1)); + } + + function testLogNamedBytes32() public { + emit log_named_bytes32("abcd", bytes32("abcd")); + } + + function testLogNamedDecimalInt() public { + emit log_named_decimal_int("amount", int256(-31337), uint256(18)); + } + + function testLogNamedDecimalUint() public { + emit log_named_decimal_uint("amount", uint256(1 ether), uint256(18)); + } + + function testLogNamedInt() public { + emit log_named_int("amount", int256(-31337)); + } + + function testLogNamedUint() public { + emit log_named_uint("amount", uint256(1 ether)); + } + + function testLogNamedBytes() public { + emit log_named_bytes("abcd", bytes("abcd")); + } + + function testLogNamedString() public { + emit log_named_string("key", "val"); + } +} + +contract Fails is Test { + function failure() public { + emit log_uint(100); + revert(); + } +} +"#, + ); + + cmd.args(["test", "-vv"]).assert_success().stdout_eq(str![[r#" +[COMPILING_FILES] with [SOLC_VERSION] +[SOLC_VERSION] [ELAPSED] +Compiler run successful! + +Ran 19 tests for test/DebugLogs.t.sol:DebugLogsTest +[PASS] test1() ([GAS]) +Logs: + 0 + 1 + 2 + +[PASS] test2() ([GAS]) +Logs: + 0 + 1 + 3 + +[PASS] testLog() ([GAS]) +Logs: + 0 + 1 + Error: Assertion Failed + +[PASS] testLogAddress() ([GAS]) +Logs: + 0 + 1 + 0x0000000000000000000000000000000000000001 + +[PASS] testLogBytes() ([GAS]) +Logs: + 0 + 1 + 0x61626364 + +[PASS] testLogBytes32() ([GAS]) +Logs: + 0 + 1 + 0x6162636400000000000000000000000000000000000000000000000000000000 + +[PASS] testLogInt() ([GAS]) +Logs: + 0 + 1 + -31337 + +[PASS] testLogNamedAddress() ([GAS]) +Logs: + 0 + 1 + address: 0x0000000000000000000000000000000000000001 + +[PASS] testLogNamedBytes() ([GAS]) +Logs: + 0 + 1 + abcd: 0x61626364 + +[PASS] testLogNamedBytes32() ([GAS]) +Logs: + 0 + 1 + abcd: 0x6162636400000000000000000000000000000000000000000000000000000000 + +[PASS] testLogNamedDecimalInt() ([GAS]) +Logs: + 0 + 1 + amount: -0.000000000000031337 + +[PASS] testLogNamedDecimalUint() ([GAS]) +Logs: + 0 + 1 + amount: 1.000000000000000000 + +[PASS] testLogNamedInt() ([GAS]) +Logs: + 0 + 1 + amount: -31337 + +[PASS] testLogNamedString() ([GAS]) +Logs: + 0 + 1 + key: val + +[PASS] testLogNamedUint() ([GAS]) +Logs: + 0 + 1 + amount: 1000000000000000000 + +[PASS] testLogString() ([GAS]) +Logs: + 0 + 1 + here + +[PASS] testLogs() ([GAS]) +Logs: + 0 + 1 + 0x61626364 + +[PASS] testRevertIfWithRequire() ([GAS]) +Logs: + 0 + 1 + 5 + +[PASS] testRevertIfWithRevert() ([GAS]) +Logs: + 0 + 1 + 4 + 100 + +Suite result: ok. 19 passed; 0 failed; 0 skipped; [ELAPSED] + +Ran 1 test suite [ELAPSED]: 19 tests passed, 0 failed, 0 skipped (19 total tests) + +"#]]); +}); + +forgetest_init!(hardhat_logs, |prj, cmd| { + prj.wipe_contracts(); + prj.add_test( + "HardhatLogs.t.sol", + r#" +import "forge-std/console.sol"; + +contract HardhatLogsTest { + constructor() { + console.log("constructor"); + } + + string testStr; + int256 testInt; + uint256 testUint; + bool testBool; + address testAddr; + bytes testBytes; + + function setUp() public { + testStr = "test"; + testInt = -31337; + testUint = 1; + testBool = false; + testAddr = 0x0000000000000000000000000000000000000001; + testBytes = "a"; + } + + function testInts() public view { + console.log(uint256(0)); + console.log(uint256(1)); + console.log(uint256(2)); + console.log(uint256(3)); + } + + function testStrings() public view { + console.log("testStrings"); + } + + function testMisc() public view { + console.log("testMisc", address(1)); + console.log("testMisc", uint256(42)); + } + + function testConsoleLog() public view { + console.log(testStr); + } + + function testLogInt() public view { + console.logInt(testInt); + } + + function testLogUint() public view { + console.logUint(testUint); + } + + function testLogString() public view { + console.logString(testStr); + } + + function testLogBool() public view { + console.logBool(testBool); + } + + function testLogAddress() public view { + console.logAddress(testAddr); + } + + function testLogBytes() public view { + console.logBytes(testBytes); + } + + function testLogBytes1() public view { + console.logBytes1(bytes1(testBytes)); + } + + function testLogBytes2() public view { + console.logBytes2(bytes2(testBytes)); + } + + function testLogBytes3() public view { + console.logBytes3(bytes3(testBytes)); + } + + function testLogBytes4() public view { + console.logBytes4(bytes4(testBytes)); + } + + function testLogBytes5() public view { + console.logBytes5(bytes5(testBytes)); + } + + function testLogBytes6() public view { + console.logBytes6(bytes6(testBytes)); + } + + function testLogBytes7() public view { + console.logBytes7(bytes7(testBytes)); + } + + function testLogBytes8() public view { + console.logBytes8(bytes8(testBytes)); + } + + function testLogBytes9() public view { + console.logBytes9(bytes9(testBytes)); + } + + function testLogBytes10() public view { + console.logBytes10(bytes10(testBytes)); + } + + function testLogBytes11() public view { + console.logBytes11(bytes11(testBytes)); + } + + function testLogBytes12() public view { + console.logBytes12(bytes12(testBytes)); + } + + function testLogBytes13() public view { + console.logBytes13(bytes13(testBytes)); + } + + function testLogBytes14() public view { + console.logBytes14(bytes14(testBytes)); + } + + function testLogBytes15() public view { + console.logBytes15(bytes15(testBytes)); + } + + function testLogBytes16() public view { + console.logBytes16(bytes16(testBytes)); + } + + function testLogBytes17() public view { + console.logBytes17(bytes17(testBytes)); + } + + function testLogBytes18() public view { + console.logBytes18(bytes18(testBytes)); + } + + function testLogBytes19() public view { + console.logBytes19(bytes19(testBytes)); + } + + function testLogBytes20() public view { + console.logBytes20(bytes20(testBytes)); + } + + function testLogBytes21() public view { + console.logBytes21(bytes21(testBytes)); + } + + function testLogBytes22() public view { + console.logBytes22(bytes22(testBytes)); + } + + function testLogBytes23() public view { + console.logBytes23(bytes23(testBytes)); + } + + function testLogBytes24() public view { + console.logBytes24(bytes24(testBytes)); + } + + function testLogBytes25() public view { + console.logBytes25(bytes25(testBytes)); + } + + function testLogBytes26() public view { + console.logBytes26(bytes26(testBytes)); + } + + function testLogBytes27() public view { + console.logBytes27(bytes27(testBytes)); + } + + function testLogBytes28() public view { + console.logBytes28(bytes28(testBytes)); + } + + function testLogBytes29() public view { + console.logBytes29(bytes29(testBytes)); + } + + function testLogBytes30() public view { + console.logBytes30(bytes30(testBytes)); + } + + function testLogBytes31() public view { + console.logBytes31(bytes31(testBytes)); + } + + function testLogBytes32() public view { + console.logBytes32(bytes32(testBytes)); + } + + function testConsoleLogUint() public view { + console.log(testUint); + } + + function testConsoleLogString() public view { + console.log(testStr); + } + + function testConsoleLogBool() public view { + console.log(testBool); + } + + function testConsoleLogAddress() public view { + console.log(testAddr); + } + + function testConsoleLogFormatString() public view { + console.log("formatted log str=%s", testStr); + } + + function testConsoleLogFormatUint() public view { + console.log("formatted log uint=%s", testUint); + } + + function testConsoleLogFormatAddress() public view { + console.log("formatted log addr=%s", testAddr); + } + + function testConsoleLogFormatMulti() public view { + console.log("formatted log str=%s uint=%d", testStr, testUint); + } + + function testConsoleLogFormatEscape() public view { + console.log("formatted log %% %s", testStr); + } + + function testConsoleLogFormatSpill() public view { + console.log("formatted log %s", testStr, testUint); + } +} +"#, + ); + + cmd.args(["test", "-vv"]).assert_success().stdout_eq(str![[r#" +... +Ran 52 tests for test/HardhatLogs.t.sol:HardhatLogsTest +[PASS] testConsoleLog() ([GAS]) +Logs: + constructor + test + +[PASS] testConsoleLogAddress() ([GAS]) +Logs: + constructor + 0x0000000000000000000000000000000000000001 + +[PASS] testConsoleLogBool() ([GAS]) +Logs: + constructor + false + +[PASS] testConsoleLogFormatAddress() ([GAS]) +Logs: + constructor + formatted log addr=0x0000000000000000000000000000000000000001 + +[PASS] testConsoleLogFormatEscape() ([GAS]) +Logs: + constructor + formatted log % test + +[PASS] testConsoleLogFormatMulti() ([GAS]) +Logs: + constructor + formatted log str=test uint=1 + +[PASS] testConsoleLogFormatSpill() ([GAS]) +Logs: + constructor + formatted log test 1 + +[PASS] testConsoleLogFormatString() ([GAS]) +Logs: + constructor + formatted log str=test + +[PASS] testConsoleLogFormatUint() ([GAS]) +Logs: + constructor + formatted log uint=1 + +[PASS] testConsoleLogString() ([GAS]) +Logs: + constructor + test + +[PASS] testConsoleLogUint() ([GAS]) +Logs: + constructor + 1 + +[PASS] testInts() ([GAS]) +Logs: + constructor + 0 + 1 + 2 + 3 + +[PASS] testLogAddress() ([GAS]) +Logs: + constructor + 0x0000000000000000000000000000000000000001 + +[PASS] testLogBool() ([GAS]) +Logs: + constructor + false + +[PASS] testLogBytes() ([GAS]) +Logs: + constructor + 0x61 + +[PASS] testLogBytes1() ([GAS]) +Logs: + constructor + 0x61 + +[PASS] testLogBytes10() ([GAS]) +Logs: + constructor + 0x61000000000000000000 + +[PASS] testLogBytes11() ([GAS]) +Logs: + constructor + 0x6100000000000000000000 + +[PASS] testLogBytes12() ([GAS]) +Logs: + constructor + 0x610000000000000000000000 + +[PASS] testLogBytes13() ([GAS]) +Logs: + constructor + 0x61000000000000000000000000 + +[PASS] testLogBytes14() ([GAS]) +Logs: + constructor + 0x6100000000000000000000000000 + +[PASS] testLogBytes15() ([GAS]) +Logs: + constructor + 0x610000000000000000000000000000 + +[PASS] testLogBytes16() ([GAS]) +Logs: + constructor + 0x61000000000000000000000000000000 + +[PASS] testLogBytes17() ([GAS]) +Logs: + constructor + 0x6100000000000000000000000000000000 + +[PASS] testLogBytes18() ([GAS]) +Logs: + constructor + 0x610000000000000000000000000000000000 + +[PASS] testLogBytes19() ([GAS]) +Logs: + constructor + 0x61000000000000000000000000000000000000 + +[PASS] testLogBytes2() ([GAS]) +Logs: + constructor + 0x6100 + +[PASS] testLogBytes20() ([GAS]) +Logs: + constructor + 0x6100000000000000000000000000000000000000 + +[PASS] testLogBytes21() ([GAS]) +Logs: + constructor + 0x610000000000000000000000000000000000000000 + +[PASS] testLogBytes22() ([GAS]) +Logs: + constructor + 0x61000000000000000000000000000000000000000000 + +[PASS] testLogBytes23() ([GAS]) +Logs: + constructor + 0x6100000000000000000000000000000000000000000000 + +[PASS] testLogBytes24() ([GAS]) +Logs: + constructor + 0x610000000000000000000000000000000000000000000000 + +[PASS] testLogBytes25() ([GAS]) +Logs: + constructor + 0x61000000000000000000000000000000000000000000000000 + +[PASS] testLogBytes26() ([GAS]) +Logs: + constructor + 0x6100000000000000000000000000000000000000000000000000 + +[PASS] testLogBytes27() ([GAS]) +Logs: + constructor + 0x610000000000000000000000000000000000000000000000000000 + +[PASS] testLogBytes28() ([GAS]) +Logs: + constructor + 0x61000000000000000000000000000000000000000000000000000000 + +[PASS] testLogBytes29() ([GAS]) +Logs: + constructor + 0x6100000000000000000000000000000000000000000000000000000000 + +[PASS] testLogBytes3() ([GAS]) +Logs: + constructor + 0x610000 + +[PASS] testLogBytes30() ([GAS]) +Logs: + constructor + 0x610000000000000000000000000000000000000000000000000000000000 + +[PASS] testLogBytes31() ([GAS]) +Logs: + constructor + 0x61000000000000000000000000000000000000000000000000000000000000 + +[PASS] testLogBytes32() ([GAS]) +Logs: + constructor + 0x6100000000000000000000000000000000000000000000000000000000000000 + +[PASS] testLogBytes4() ([GAS]) +Logs: + constructor + 0x61000000 + +[PASS] testLogBytes5() ([GAS]) +Logs: + constructor + 0x6100000000 + +[PASS] testLogBytes6() ([GAS]) +Logs: + constructor + 0x610000000000 + +[PASS] testLogBytes7() ([GAS]) +Logs: + constructor + 0x61000000000000 + +[PASS] testLogBytes8() ([GAS]) +Logs: + constructor + 0x6100000000000000 + +[PASS] testLogBytes9() ([GAS]) +Logs: + constructor + 0x610000000000000000 + +[PASS] testLogInt() ([GAS]) +Logs: + constructor + -31337 + +[PASS] testLogString() ([GAS]) +Logs: + constructor + test + +[PASS] testLogUint() ([GAS]) +Logs: + constructor + 1 + +[PASS] testMisc() ([GAS]) +Logs: + constructor + testMisc 0x0000000000000000000000000000000000000001 + testMisc 42 + +[PASS] testStrings() ([GAS]) +Logs: + constructor + testStrings + +Suite result: ok. 52 passed; 0 failed; 0 skipped; [ELAPSED] + +Ran 1 test suite [ELAPSED]: 52 tests passed, 0 failed, 0 skipped (52 total tests) + +"#]]); +}); diff --git a/crates/forge/tests/cli/test_cmd.rs b/crates/forge/tests/cli/test_cmd/mod.rs similarity index 98% rename from crates/forge/tests/cli/test_cmd.rs rename to crates/forge/tests/cli/test_cmd/mod.rs index 11bbc782af2b6..d708cbf4123a7 100644 --- a/crates/forge/tests/cli/test_cmd.rs +++ b/crates/forge/tests/cli/test_cmd/mod.rs @@ -3,11 +3,63 @@ use alloy_primitives::U256; use anvil::{NodeConfig, spawn}; use foundry_test_utils::{ - TestCommand, rpc, str, + TestCommand, + rpc::{self, rpc_endpoints}, + str, util::{OTHER_SOLC_VERSION, OutputExt, SOLC_VERSION}, }; use similar_asserts::assert_eq; -use std::{path::PathBuf, str::FromStr}; +use std::{io::Write, path::PathBuf, str::FromStr}; + +mod core; +mod fuzz; +mod invariant; +mod logs; +mod repros; +mod spec; +mod trace; + +// Run `forge test` on `/testdata`. +forgetest!(testdata, |_prj, cmd| { + let testdata = + PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../../testdata").canonicalize().unwrap(); + cmd.current_dir(&testdata); + + let mut dotenv = std::fs::File::create(testdata.join(".env")).unwrap(); + for (name, endpoint) in rpc_endpoints().iter() { + if let Some(url) = endpoint.endpoint.as_url() { + let key = format!("RPC_{}", name.to_uppercase()); + // cmd.env(&key, url); + writeln!(dotenv, "{key}={url}").unwrap(); + } + } + drop(dotenv); + + let mut args = vec!["test"]; + if cfg!(feature = "isolate-by-default") { + args.push( + "--nmc=(LastCallGasDefaultTest|MockFunctionTest|WithSeed|StateDiff|GetStorageSlotsTest|RecordAccount)", + ); + } + + let orig_assert = cmd.args(args).assert(); + if orig_assert.get_output().status.success() { + return; + } + + // Retry failed tests. + cmd.args(["--rerun"]); + let n = 3; + for i in 1..=n { + test_debug!("retrying failed tests... ({i}/{n})"); + let assert = cmd.assert(); + if assert.get_output().status.success() { + return; + } + } + + orig_assert.success(); +}); // tests that test filters are handled correctly forgetest!(can_set_filter_values, |prj, cmd| { @@ -272,7 +324,7 @@ forgetest!(can_run_test_with_json_output_verbose, |prj, cmd| { // Assert that with verbose output the json output includes the traces cmd.args(["test", "-vvv", "--json"]) .assert_success() - .stdout_eq(file!["../fixtures/SimpleContractTestVerbose.json": Json]); + .stdout_eq(file!["../../fixtures/SimpleContractTestVerbose.json": Json]); }); forgetest!(can_run_test_with_json_output_non_verbose, |prj, cmd| { @@ -284,7 +336,7 @@ forgetest!(can_run_test_with_json_output_non_verbose, |prj, cmd| { // Assert that without verbose output the json output does not include the traces cmd.args(["test", "--json"]) .assert_success() - .stdout_eq(file!["../fixtures/SimpleContractTestNonVerbose.json": Json]); + .stdout_eq(file!["../../fixtures/SimpleContractTestNonVerbose.json": Json]); }); // tests that `forge test` will pick up tests that are stored in the `test = ` config value @@ -2931,7 +2983,7 @@ Ran 1 test suite [ELAPSED]: 1 tests passed, 0 failed, 0 skipped (1 total tests) forgetest_init!(colored_traces, |prj, cmd| { cmd.args(["test", "--mt", "test_Increment", "--color", "always", "-vvvvv"]) .assert_success() - .stdout_eq(file!["../fixtures/colored_traces.svg": TermSvg]); + .stdout_eq(file!["../../fixtures/colored_traces.svg": TermSvg]); }); // Tests that traces for successful tests can be suppressed by using `-s` flag. diff --git a/testdata/default/repros/Issue8383.t.sol b/crates/forge/tests/cli/test_cmd/repros.rs similarity index 57% rename from testdata/default/repros/Issue8383.t.sol rename to crates/forge/tests/cli/test_cmd/repros.rs index 3c40e44475fcc..bb663c051fa63 100644 --- a/testdata/default/repros/Issue8383.t.sol +++ b/crates/forge/tests/cli/test_cmd/repros.rs @@ -1,13 +1,438 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.18; +//! Regression tests for specific GitHub issues -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +use foundry_test_utils::str; + +// https://github.com/foundry-rs/foundry/issues/3055 +forgetest_init!(issue_3055, |prj, cmd| { + prj.wipe_contracts(); + prj.add_test( + "Issue3055.t.sol", + r#" +import "forge-std/Test.sol"; + +/// forge-config: default.assertions_revert = false +contract Issue3055Test is Test { + function test_snapshot() external { + uint256 snapshotId = vm.snapshotState(); + assertEq(uint256(0), uint256(1)); + vm.revertToState(snapshotId); + } + + function test_snapshot2() public { + uint256 snapshotId = vm.snapshotState(); + assertTrue(false); + vm.revertToState(snapshotId); + assertTrue(true); + } + + function test_snapshot3(uint256) public { + vm.expectRevert(); + // Call exposed_snapshot3() using this to perform an external call, + // so we can properly test for reverts. + this.exposed_snapshot3(); + } + + function exposed_snapshot3() public { + uint256 snapshotId = vm.snapshotState(); + assertTrue(false); + vm.revertToState(snapshotId); + } +} +"#, + ); + + cmd.arg("test").assert_failure().stdout_eq(str![[r#" +[COMPILING_FILES] with [SOLC_VERSION] +[SOLC_VERSION] [ELAPSED] +Compiler run successful! + +Ran 3 tests for test/Issue3055.t.sol:Issue3055Test +[FAIL] test_snapshot() ([GAS]) +[FAIL] test_snapshot2() ([GAS]) +[FAIL: next call did not revert as expected; counterexample: calldata=[..] args=[..] test_snapshot3(uint256) (runs: 0, [AVG_GAS]) +Suite result: FAILED. 0 passed; 3 failed; 0 skipped; [ELAPSED] + +Ran 1 test suite [ELAPSED]: 0 tests passed, 3 failed, 0 skipped (3 total tests) + +Failing tests: +Encountered 3 failing tests in test/Issue3055.t.sol:Issue3055Test +[FAIL] test_snapshot() ([GAS]) +[FAIL] test_snapshot2() ([GAS]) +[FAIL: next call did not revert as expected; counterexample: calldata=[..] args=[..] test_snapshot3(uint256) (runs: 0, [AVG_GAS]) + +Encountered a total of 3 failing tests, 0 tests succeeded + +Tip: Run `forge test --rerun` to retry only the 3 failed tests + +"#]]); +}); + +// https://github.com/foundry-rs/foundry/issues/3189 +forgetest_init!(issue_3189, |prj, cmd| { + prj.wipe_contracts(); + prj.add_test( + "Issue3189.t.sol", + r#" +import "forge-std/Test.sol"; + +contract MyContract { + function foo(uint256 arg) public returns (uint256) { + return arg + 2; + } +} + +contract MyContractUser is Test { + MyContract immutable myContract; + + constructor() { + myContract = new MyContract(); + } + + function foo(uint256 arg) public returns (uint256 ret) { + ret = myContract.foo(arg); + assertEq(ret, arg + 1, "Invariant failed"); + } +} + +contract Issue3189Test is Test { + function testFoo() public { + MyContractUser user = new MyContractUser(); + user.foo(123); + } +} +"#, + ); + + cmd.arg("test").assert_failure().stdout_eq(str![[r#" +... +Ran 1 test for test/Issue3189.t.sol:Issue3189Test +[FAIL: Invariant failed: 125 != 124] testFoo() ([GAS]) +Suite result: FAILED. 0 passed; 1 failed; 0 skipped; [ELAPSED] + +Ran 1 test suite [ELAPSED]: 0 tests passed, 1 failed, 0 skipped (1 total tests) + +Failing tests: +Encountered 1 failing test in test/Issue3189.t.sol:Issue3189Test +[FAIL: Invariant failed: 125 != 124] testFoo() ([GAS]) + +Encountered a total of 1 failing tests, 0 tests succeeded + +Tip: Run `forge test --rerun` to retry only the 1 failed test + +"#]]); +}); + +// https://github.com/foundry-rs/foundry/issues/3596 +forgetest_init!(issue_3596, |prj, cmd| { + prj.wipe_contracts(); + prj.add_test( + "Issue3596.t.sol", + r#" +import "forge-std/Test.sol"; + +contract Issue3596Test is Test { + function testDealTransfer() public { + address addr = vm.addr(1337); + vm.startPrank(addr); + vm.deal(addr, 20000001 ether); + payable(address(this)).transfer(20000000 ether); + + Nested nested = new Nested(); + nested.doStuff(); + vm.stopPrank(); + } +} + +contract Nested { + function doStuff() public { + doRevert(); + } + + function doRevert() public { + revert("This fails"); + } +} +"#, + ); + + cmd.arg("test").assert_failure().stdout_eq(str![[r#" +... +Ran 1 test for test/Issue3596.t.sol:Issue3596Test +[FAIL: EvmError: Revert] testDealTransfer() ([GAS]) +Suite result: FAILED. 0 passed; 1 failed; 0 skipped; [ELAPSED] + +Ran 1 test suite [ELAPSED]: 0 tests passed, 1 failed, 0 skipped (1 total tests) + +Failing tests: +Encountered 1 failing test in test/Issue3596.t.sol:Issue3596Test +[FAIL: EvmError: Revert] testDealTransfer() ([GAS]) + +Encountered a total of 1 failing tests, 0 tests succeeded + +Tip: Run `forge test --rerun` to retry only the 1 failed test + +"#]]); +}); + +// https://github.com/foundry-rs/foundry/issues/2851 +forgetest_init!(issue_2851, |prj, cmd| { + prj.wipe_contracts(); + prj.add_test( + "Issue2851.t.sol", + r#" +import "forge-std/Test.sol"; + +contract Backdoor { + uint256 public number = 1; + + function backdoor(uint256 newNumber) public payable { + uint256 x = newNumber - 1; + if (x == 6912213124124531) { + number = 0; + } + } +} + +contract Issue2851Test is Test { + Backdoor back; + + function setUp() public { + back = new Backdoor(); + } + + /// forge-config: default.fuzz.seed = "111" + function invariantNotZero() public { + assertEq(back.number(), 1); + } +} +"#, + ); + + cmd.arg("test").assert_failure().stdout_eq(str![[r#" +... +Ran 1 test for test/Issue2851.t.sol:Issue2851Test +[FAIL: assertion failed: 0 != 1] +... + invariantNotZero() ([..]) +... +Suite result: FAILED. 0 passed; 1 failed; 0 skipped; [ELAPSED] + +Ran 1 test suite [ELAPSED]: 0 tests passed, 1 failed, 0 skipped (1 total tests) +... +"#]]); +}); + +// https://github.com/foundry-rs/foundry/issues/6170 +forgetest_init!(issue_6170, |prj, cmd| { + prj.wipe_contracts(); + prj.add_test( + "Issue6170.t.sol", + r#" +import "forge-std/Test.sol"; + +contract Emitter { + event Values(uint256 indexed a, uint256 indexed b); + + function plsEmit(uint256 a, uint256 b) external { + emit Values(a, b); + } +} + +contract Issue6170Test is Test { + event Values(uint256 indexed a, uint256 b); + + Emitter e = new Emitter(); + + function test() public { + vm.expectEmit(true, true, false, true); + emit Values(69, 420); + e.plsEmit(69, 420); + } +} +"#, + ); + + cmd.arg("test").assert_failure().stdout_eq(str![[r#" +[COMPILING_FILES] with [SOLC_VERSION] +[SOLC_VERSION] [ELAPSED] +Compiler run successful! + +Ran 1 test for test/Issue6170.t.sol:Issue6170Test +[FAIL: log != expected log] test() ([GAS]) +Suite result: FAILED. 0 passed; 1 failed; 0 skipped; [ELAPSED] + +Ran 1 test suite [ELAPSED]: 0 tests passed, 1 failed, 0 skipped (1 total tests) + +Failing tests: +Encountered 1 failing test in test/Issue6170.t.sol:Issue6170Test +[FAIL: log != expected log] test() ([GAS]) + +Encountered a total of 1 failing tests, 0 tests succeeded + +Tip: Run `forge test --rerun` to retry only the 1 failed test + +"#]]); +}); + +// https://github.com/foundry-rs/foundry/issues/6355 +forgetest_init!(issue_6355, |prj, cmd| { + prj.wipe_contracts(); + prj.add_test( + "Issue6355.t.sol", + r#" +import "forge-std/Test.sol"; + +contract Issue6355Test is Test { + uint256 snapshotId; + Target targ; + + function setUp() public { + snapshotId = vm.snapshotState(); + targ = new Target(); + } + + // this non-deterministically fails sometimes and passes sometimes + function test_shouldPass() public { + assertEq(2, targ.num()); + } + + // always fails + function test_shouldFailWithRevertToState() public { + assertEq(3, targ.num()); + vm.revertToState(snapshotId); + } + + // always fails + function test_shouldFail() public { + assertEq(3, targ.num()); + } +} + +contract Target { + function num() public pure returns (uint256) { + return 2; + } +} +"#, + ); + + cmd.arg("test").assert_failure().stdout_eq(str![[r#" +... +Ran 3 tests for test/Issue6355.t.sol:Issue6355Test +[FAIL: assertion failed: 3 != 2] test_shouldFail() ([GAS]) +[FAIL: assertion failed: 3 != 2] test_shouldFailWithRevertToState() ([GAS]) +[PASS] test_shouldPass() ([GAS]) +Suite result: FAILED. 1 passed; 2 failed; 0 skipped; [ELAPSED] + +Ran 1 test suite [ELAPSED]: 1 tests passed, 2 failed, 0 skipped (3 total tests) + +Failing tests: +Encountered 2 failing tests in test/Issue6355.t.sol:Issue6355Test +[FAIL: assertion failed: 3 != 2] test_shouldFail() ([GAS]) +[FAIL: assertion failed: 3 != 2] test_shouldFailWithRevertToState() ([GAS]) + +Encountered a total of 2 failing tests, 1 tests succeeded + +Tip: Run `forge test --rerun` to retry only the 2 failed tests + +"#]]); +}); + +// https://github.com/foundry-rs/foundry/issues/3347 +forgetest_init!(issue_3347, |prj, cmd| { + prj.wipe_contracts(); + prj.add_test( + "Issue3347.t.sol", + r#" +import "forge-std/Test.sol"; + +contract Issue3347Test is Test { + event log2(uint256, uint256); + + function test() public { + emit log2(1, 2); + } +} +"#, + ); + + cmd.args(["test", "-vvvv"]).assert_success().stdout_eq(str![[r#" +[COMPILING_FILES] with [SOLC_VERSION] +[SOLC_VERSION] [ELAPSED] +Compiler run successful! + +Ran 1 test for test/Issue3347.t.sol:Issue3347Test +[PASS] test() ([GAS]) +Traces: + [..] Issue3347Test::test() + ├─ emit log2(: 1, : 2) + └─ ← [Stop] + +Suite result: ok. 1 passed; 0 failed; 0 skipped; [ELAPSED] + +Ran 1 test suite [ELAPSED]: 1 tests passed, 0 failed, 0 skipped (1 total tests) + +"#]]); +}); + +// https://github.com/foundry-rs/foundry/issues/6501 +// Make sure we decode Hardhat-style `console.log`s correctly, in both logs and traces. +forgetest_init!(issue_6501, |prj, cmd| { + prj.wipe_contracts(); + prj.add_test( + "Issue6501.t.sol", + r#" +import "forge-std/Test.sol"; + +contract Issue6501Test is Test { + function test_hhLogs() public { + console.log("a"); + console.log(uint256(1)); + console.log("b", uint256(2)); + } +} +"#, + ); + + cmd.args(["test", "-vvvv"]).assert_success().stdout_eq(str![[r#" +... +Ran 1 test for test/Issue6501.t.sol:Issue6501Test +[PASS] test_hhLogs() ([GAS]) +Logs: + a + 1 + b 2 + +Traces: + [..] Issue6501Test::test_hhLogs() + ├─ [0] console::log("a") [staticcall] + │ └─ ← [Stop] + ├─ [0] console::log(1) [staticcall] + │ └─ ← [Stop] + ├─ [0] console::log("b", 2) [staticcall] + │ └─ ← [Stop] + └─ ← [Stop] + +Suite result: ok. 1 passed; 0 failed; 0 skipped; [ELAPSED] + +Ran 1 test suite [ELAPSED]: 1 tests passed, 0 failed, 0 skipped (1 total tests) + +"#]]); +}); // https://github.com/foundry-rs/foundry/issues/8383 -contract Issue8383Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +forgetest_init!(issue_8383, |prj, cmd| { + prj.wipe_contracts(); + prj.update_config(|config| { + config.optimizer = Some(true); + config.optimizer_runs = Some(200); + }); + prj.add_test( + "Issue8383.t.sol", + r#" +import "forge-std/Test.sol"; +contract Issue8383Test is Test { address internal _verifier; mapping(bytes32 => bool) internal _vectorTested; @@ -326,3 +751,13 @@ contract P256Verifier { } } } +"#, + ); + + cmd.arg("test").with_no_redact().assert_success().stdout_eq(str![[r#" +... +Ran 1 test for test/Issue8383.t.sol:Issue8383Test +[PASS] testP256VerifyOutOfBounds() (gas: 3139) +... +"#]]); +}); diff --git a/crates/forge/tests/it/spec.rs b/crates/forge/tests/cli/test_cmd/spec.rs similarity index 93% rename from crates/forge/tests/it/spec.rs rename to crates/forge/tests/cli/test_cmd/spec.rs index bcd16ce08028a..d8eabfad548e6 100644 --- a/crates/forge/tests/it/spec.rs +++ b/crates/forge/tests/cli/test_cmd/spec.rs @@ -1,19 +1,10 @@ -//! Integration tests for EVM specifications. - -use crate::{config::*, test_helpers::TEST_DATA_PARIS}; -use foundry_test_utils::{Filter, forgetest_init, rpc, str}; -use revm::primitives::hardfork::SpecId; - -#[tokio::test(flavor = "multi_thread")] -async fn test_shanghai_compat() { - let filter = Filter::new("", "ShanghaiCompat", ".*spec"); - TestConfig::with_filter(TEST_DATA_PARIS.runner(), filter).spec_id(SpecId::SHANGHAI).run().await; -} +use foundry_test_utils::rpc; // Test evm version switch during tests / scripts. // // forgetest_init!(test_set_evm_version, |prj, cmd| { + prj.wipe_contracts(); let endpoint = rpc::next_http_archive_rpc_url(); prj.add_test( "TestEvmVersion.t.sol", diff --git a/crates/forge/tests/it/table.rs b/crates/forge/tests/cli/test_cmd/table.rs similarity index 100% rename from crates/forge/tests/it/table.rs rename to crates/forge/tests/cli/test_cmd/table.rs diff --git a/crates/forge/tests/cli/test_cmd/trace.rs b/crates/forge/tests/cli/test_cmd/trace.rs new file mode 100644 index 0000000000000..093afbbdb8fe5 --- /dev/null +++ b/crates/forge/tests/cli/test_cmd/trace.rs @@ -0,0 +1,397 @@ +//! Tests for tracing functionality + +use foundry_test_utils::str; + +forgetest_init!(conflicting_signatures, |prj, cmd| { + prj.wipe_contracts(); + prj.add_test( + "ConflictingSignatures.t.sol", + r#" +pragma solidity ^0.8.18; + +import "forge-std/Test.sol"; + +contract ReturnsNothing { + function func() public pure {} +} + +contract ReturnsString { + function func() public pure returns (string memory) { + return "string"; + } +} + +contract ReturnsUint { + function func() public pure returns (uint256) { + return 1; + } +} + +contract ConflictingSignaturesTest is Test { + ReturnsNothing retsNothing; + ReturnsString retsString; + ReturnsUint retsUint; + + function setUp() public { + retsNothing = new ReturnsNothing(); + retsString = new ReturnsString(); + retsUint = new ReturnsUint(); + } + + /// Tests that traces are decoded properly when multiple + /// functions have the same 4byte signature, but different + /// return values. + function testTraceWithConflictingSignatures() public { + retsNothing.func(); + retsString.func(); + retsUint.func(); + } +} +"#, + ); + + cmd.args(["test", "-vvvvv"]).assert_success().stdout_eq(str![[r#" +... +Ran 1 test for test/ConflictingSignatures.t.sol:ConflictingSignaturesTest +[PASS] testTraceWithConflictingSignatures() ([GAS]) +Traces: + [..] ConflictingSignaturesTest::setUp() + ├─ [..] → new ReturnsNothing@0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f + │ └─ ← [Return] 106 bytes of code + ├─ [..] → new ReturnsString@0x2e234DAe75C793f67A35089C9d99245E1C58470b + │ └─ ← [Return] 334 bytes of code + ├─ [..] → new ReturnsUint@0xF62849F9A0B5Bf2913b396098F7c7019b51A820a + │ └─ ← [Return] 175 bytes of code + └─ ← [Stop] + + [..] ConflictingSignaturesTest::testTraceWithConflictingSignatures() + ├─ [..] ReturnsNothing::func() [staticcall] + │ └─ ← [Stop] + ├─ [..] ReturnsString::func() [staticcall] + │ └─ ← [Return] 0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000006737472696e670000000000000000000000000000000000000000000000000000 + ├─ [..] ReturnsUint::func() [staticcall] + │ └─ ← [Return] 0x0000000000000000000000000000000000000000000000000000000000000001 + └─ ← [Stop] + +Suite result: ok. 1 passed; 0 failed; 0 skipped; [ELAPSED] + +Ran 1 test suite [ELAPSED]: 1 tests passed, 0 failed, 0 skipped (1 total tests) + +"#]]); +}); + +#[cfg(not(feature = "isolate-by-default"))] +forgetest_init!(trace_test, |prj, cmd| { + prj.wipe_contracts(); + prj.add_test( + "Trace.t.sol", + r#" +pragma solidity ^0.8.18; + +import "forge-std/Test.sol"; + +contract RecursiveCall { + TraceTest factory; + + event Depth(uint256 depth); + event ChildDepth(uint256 childDepth); + event CreatedChild(uint256 childDepth); + + constructor(address _factory) { + factory = TraceTest(_factory); + } + + function recurseCall(uint256 neededDepth, uint256 depth) public returns (uint256) { + if (depth == neededDepth) { + this.negativeNum(); + return neededDepth; + } + + uint256 childDepth = this.recurseCall(neededDepth, depth + 1); + emit ChildDepth(childDepth); + + this.someCall(); + emit Depth(depth); + + return depth; + } + + function recurseCreate(uint256 neededDepth, uint256 depth) public returns (uint256) { + if (depth == neededDepth) { + return neededDepth; + } + + RecursiveCall child = factory.create(); + emit CreatedChild(depth + 1); + + uint256 childDepth = child.recurseCreate(neededDepth, depth + 1); + emit ChildDepth(childDepth); + emit Depth(depth); + + return depth; + } + + function someCall() public pure {} + + function negativeNum() public pure returns (int256) { + return -1000000000; + } +} + +contract TraceTest is Test { + uint256 nodeId = 0; + RecursiveCall first; + + function setUp() public { + first = this.create(); + } + + function create() public returns (RecursiveCall) { + RecursiveCall node = new RecursiveCall(address(this)); + vm.label(address(node), string(abi.encodePacked("Node ", uintToString(nodeId++)))); + + return node; + } + + function testRecurseCall() public { + first.recurseCall(8, 0); + } + + function testRecurseCreate() public { + first.recurseCreate(8, 0); + } +} + +function uintToString(uint256 value) pure returns (string memory) { + // Taken from OpenZeppelin + if (value == 0) { + return "0"; + } + uint256 temp = value; + uint256 digits; + while (temp != 0) { + digits++; + temp /= 10; + } + bytes memory buffer = new bytes(digits); + while (value != 0) { + digits -= 1; + buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); + value /= 10; + } + return string(buffer); +} +"#, + ); + + cmd.args(["test", "-vvvvv"]).assert_success().stdout_eq(str![[r#" +... +Ran 2 tests for test/Trace.t.sol:TraceTest +[PASS] testRecurseCall() ([GAS]) +Traces: + [..] TraceTest::setUp() + ├─ [..] TraceTest::create() + │ ├─ [..] → new Node 0@0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f + │ │ └─ ← [Return] 1911 bytes of code + │ ├─ [0] VM::label(Node 0: [0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f], "Node 0") + │ │ └─ ← [Return] + │ └─ ← [Return] Node 0: [0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f] + └─ ← [Stop] + + [..] TraceTest::testRecurseCall() + ├─ [..] Node 0::recurseCall(8, 0) + │ ├─ [..] Node 0::recurseCall(8, 1) + │ │ ├─ [..] Node 0::recurseCall(8, 2) + │ │ │ ├─ [..] Node 0::recurseCall(8, 3) + │ │ │ │ ├─ [..] Node 0::recurseCall(8, 4) + │ │ │ │ │ ├─ [..] Node 0::recurseCall(8, 5) + │ │ │ │ │ │ ├─ [..] Node 0::recurseCall(8, 6) + │ │ │ │ │ │ │ ├─ [..] Node 0::recurseCall(8, 7) + │ │ │ │ │ │ │ │ ├─ [..] Node 0::recurseCall(8, 8) + │ │ │ │ │ │ │ │ │ ├─ [..] Node 0::negativeNum() [staticcall] + │ │ │ │ │ │ │ │ │ │ └─ ← [Return] -1000000000 [-1e9] + │ │ │ │ │ │ │ │ │ └─ ← [Return] 8 + │ │ │ │ │ │ │ │ ├─ emit ChildDepth(childDepth: 8) + │ │ │ │ │ │ │ │ ├─ [..] Node 0::someCall() [staticcall] + │ │ │ │ │ │ │ │ │ └─ ← [Stop] + │ │ │ │ │ │ │ │ ├─ emit Depth(depth: 7) + │ │ │ │ │ │ │ │ └─ ← [Return] 7 + │ │ │ │ │ │ │ ├─ emit ChildDepth(childDepth: 7) + │ │ │ │ │ │ │ ├─ [..] Node 0::someCall() [staticcall] + │ │ │ │ │ │ │ │ └─ ← [Stop] + │ │ │ │ │ │ │ ├─ emit Depth(depth: 6) + │ │ │ │ │ │ │ └─ ← [Return] 6 + │ │ │ │ │ │ ├─ emit ChildDepth(childDepth: 6) + │ │ │ │ │ │ ├─ [..] Node 0::someCall() [staticcall] + │ │ │ │ │ │ │ └─ ← [Stop] + │ │ │ │ │ │ ├─ emit Depth(depth: 5) + │ │ │ │ │ │ └─ ← [Return] 5 + │ │ │ │ │ ├─ emit ChildDepth(childDepth: 5) + │ │ │ │ │ ├─ [..] Node 0::someCall() [staticcall] + │ │ │ │ │ │ └─ ← [Stop] + │ │ │ │ │ ├─ emit Depth(depth: 4) + │ │ │ │ │ └─ ← [Return] 4 + │ │ │ │ ├─ emit ChildDepth(childDepth: 4) + │ │ │ │ ├─ [..] Node 0::someCall() [staticcall] + │ │ │ │ │ └─ ← [Stop] + │ │ │ │ ├─ emit Depth(depth: 3) + │ │ │ │ └─ ← [Return] 3 + │ │ │ ├─ emit ChildDepth(childDepth: 3) + │ │ │ ├─ [..] Node 0::someCall() [staticcall] + │ │ │ │ └─ ← [Stop] + │ │ │ ├─ emit Depth(depth: 2) + │ │ │ └─ ← [Return] 2 + │ │ ├─ emit ChildDepth(childDepth: 2) + │ │ ├─ [..] Node 0::someCall() [staticcall] + │ │ │ └─ ← [Stop] + │ │ ├─ emit Depth(depth: 1) + │ │ └─ ← [Return] 1 + │ ├─ emit ChildDepth(childDepth: 1) + │ ├─ [..] Node 0::someCall() [staticcall] + │ │ └─ ← [Stop] + │ ├─ emit Depth(depth: 0) + │ └─ ← [Return] 0 + └─ ← [Stop] + +[PASS] testRecurseCreate() ([GAS]) +Traces: + [..] TraceTest::setUp() + ├─ [..] TraceTest::create() + │ ├─ [..] → new Node 0@0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f + │ │ └─ ← [Return] 1911 bytes of code + │ ├─ [0] VM::label(Node 0: [0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f], "Node 0") + │ │ └─ ← [Return] + │ └─ ← [Return] Node 0: [0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f] + └─ ← [Stop] + + [..] TraceTest::testRecurseCreate() + ├─ [..] Node 0::recurseCreate(8, 0) + │ ├─ [..] TraceTest::create() + │ │ ├─ [..] → new Node 1@0x2e234DAe75C793f67A35089C9d99245E1C58470b + │ │ │ ├─ storage changes: + │ │ │ │ @ 0: 0 → 0x0000000000000000000000007fa9385be102ac3eac297483dd6233d62b3e1496 + │ │ │ └─ ← [Return] 1911 bytes of code + │ │ ├─ [0] VM::label(Node 1: [0x2e234DAe75C793f67A35089C9d99245E1C58470b], "Node 1") + │ │ │ └─ ← [Return] + │ │ ├─ storage changes: + │ │ │ @ 32: 1 → 2 + │ │ └─ ← [Return] Node 1: [0x2e234DAe75C793f67A35089C9d99245E1C58470b] + │ ├─ emit CreatedChild(childDepth: 1) + │ ├─ [..] Node 1::recurseCreate(8, 1) + │ │ ├─ [..] TraceTest::create() + │ │ │ ├─ [..] → new Node 2@0xF62849F9A0B5Bf2913b396098F7c7019b51A820a + │ │ │ │ ├─ storage changes: + │ │ │ │ │ @ 0: 0 → 0x0000000000000000000000007fa9385be102ac3eac297483dd6233d62b3e1496 + │ │ │ │ └─ ← [Return] 1911 bytes of code + │ │ │ ├─ [0] VM::label(Node 2: [0xF62849F9A0B5Bf2913b396098F7c7019b51A820a], "Node 2") + │ │ │ │ └─ ← [Return] + │ │ │ ├─ storage changes: + │ │ │ │ @ 32: 2 → 3 + │ │ │ └─ ← [Return] Node 2: [0xF62849F9A0B5Bf2913b396098F7c7019b51A820a] + │ │ ├─ emit CreatedChild(childDepth: 2) + │ │ ├─ [..] Node 2::recurseCreate(8, 2) + │ │ │ ├─ [..] TraceTest::create() + │ │ │ │ ├─ [..] → new Node 3@0x5991A2dF15A8F6A256D3Ec51E99254Cd3fb576A9 + │ │ │ │ │ ├─ storage changes: + │ │ │ │ │ │ @ 0: 0 → 0x0000000000000000000000007fa9385be102ac3eac297483dd6233d62b3e1496 + │ │ │ │ │ └─ ← [Return] 1911 bytes of code + │ │ │ │ ├─ [0] VM::label(Node 3: [0x5991A2dF15A8F6A256D3Ec51E99254Cd3fb576A9], "Node 3") + │ │ │ │ │ └─ ← [Return] + │ │ │ │ ├─ storage changes: + │ │ │ │ │ @ 32: 3 → 4 + │ │ │ │ └─ ← [Return] Node 3: [0x5991A2dF15A8F6A256D3Ec51E99254Cd3fb576A9] + │ │ │ ├─ emit CreatedChild(childDepth: 3) + │ │ │ ├─ [..] Node 3::recurseCreate(8, 3) + │ │ │ │ ├─ [..] TraceTest::create() + │ │ │ │ │ ├─ [..] → new Node 4@0xc7183455a4C133Ae270771860664b6B7ec320bB1 + │ │ │ │ │ │ ├─ storage changes: + │ │ │ │ │ │ │ @ 0: 0 → 0x0000000000000000000000007fa9385be102ac3eac297483dd6233d62b3e1496 + │ │ │ │ │ │ └─ ← [Return] 1911 bytes of code + │ │ │ │ │ ├─ [0] VM::label(Node 4: [0xc7183455a4C133Ae270771860664b6B7ec320bB1], "Node 4") + │ │ │ │ │ │ └─ ← [Return] + │ │ │ │ │ ├─ storage changes: + │ │ │ │ │ │ @ 32: 4 → 5 + │ │ │ │ │ └─ ← [Return] Node 4: [0xc7183455a4C133Ae270771860664b6B7ec320bB1] + │ │ │ │ ├─ emit CreatedChild(childDepth: 4) + │ │ │ │ ├─ [..] Node 4::recurseCreate(8, 4) + │ │ │ │ │ ├─ [..] TraceTest::create() + │ │ │ │ │ │ ├─ [..] → new Node 5@0xa0Cb889707d426A7A386870A03bc70d1b0697598 + │ │ │ │ │ │ │ ├─ storage changes: + │ │ │ │ │ │ │ │ @ 0: 0 → 0x0000000000000000000000007fa9385be102ac3eac297483dd6233d62b3e1496 + │ │ │ │ │ │ │ └─ ← [Return] 1911 bytes of code + │ │ │ │ │ │ ├─ [0] VM::label(Node 5: [0xa0Cb889707d426A7A386870A03bc70d1b0697598], "Node 5") + │ │ │ │ │ │ │ └─ ← [Return] + │ │ │ │ │ │ ├─ storage changes: + │ │ │ │ │ │ │ @ 32: 5 → 6 + │ │ │ │ │ │ └─ ← [Return] Node 5: [0xa0Cb889707d426A7A386870A03bc70d1b0697598] + │ │ │ │ │ ├─ emit CreatedChild(childDepth: 5) + │ │ │ │ │ ├─ [..] Node 5::recurseCreate(8, 5) + │ │ │ │ │ │ ├─ [..] TraceTest::create() + │ │ │ │ │ │ │ ├─ [..] → new Node 6@0x1d1499e622D69689cdf9004d05Ec547d650Ff211 + │ │ │ │ │ │ │ │ ├─ storage changes: + │ │ │ │ │ │ │ │ │ @ 0: 0 → 0x0000000000000000000000007fa9385be102ac3eac297483dd6233d62b3e1496 + │ │ │ │ │ │ │ │ └─ ← [Return] 1911 bytes of code + │ │ │ │ │ │ │ ├─ [0] VM::label(Node 6: [0x1d1499e622D69689cdf9004d05Ec547d650Ff211], "Node 6") + │ │ │ │ │ │ │ │ └─ ← [Return] + │ │ │ │ │ │ │ ├─ storage changes: + │ │ │ │ │ │ │ │ @ 32: 6 → 7 + │ │ │ │ │ │ │ └─ ← [Return] Node 6: [0x1d1499e622D69689cdf9004d05Ec547d650Ff211] + │ │ │ │ │ │ ├─ emit CreatedChild(childDepth: 6) + │ │ │ │ │ │ ├─ [..] Node 6::recurseCreate(8, 6) + │ │ │ │ │ │ │ ├─ [..] TraceTest::create() + │ │ │ │ │ │ │ │ ├─ [..] → new Node 7@0xA4AD4f68d0b91CFD19687c881e50f3A00242828c + │ │ │ │ │ │ │ │ │ ├─ storage changes: + │ │ │ │ │ │ │ │ │ │ @ 0: 0 → 0x0000000000000000000000007fa9385be102ac3eac297483dd6233d62b3e1496 + │ │ │ │ │ │ │ │ │ └─ ← [Return] 1911 bytes of code + │ │ │ │ │ │ │ │ ├─ [0] VM::label(Node 7: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c], "Node 7") + │ │ │ │ │ │ │ │ │ └─ ← [Return] + │ │ │ │ │ │ │ │ ├─ storage changes: + │ │ │ │ │ │ │ │ │ @ 32: 7 → 8 + │ │ │ │ │ │ │ │ └─ ← [Return] Node 7: [0xA4AD4f68d0b91CFD19687c881e50f3A00242828c] + │ │ │ │ │ │ │ ├─ emit CreatedChild(childDepth: 7) + │ │ │ │ │ │ │ ├─ [..] Node 7::recurseCreate(8, 7) + │ │ │ │ │ │ │ │ ├─ [..] TraceTest::create() + │ │ │ │ │ │ │ │ │ ├─ [..] → new Node 8@0x03A6a84cD762D9707A21605b548aaaB891562aAb + │ │ │ │ │ │ │ │ │ │ ├─ storage changes: + │ │ │ │ │ │ │ │ │ │ │ @ 0: 0 → 0x0000000000000000000000007fa9385be102ac3eac297483dd6233d62b3e1496 + │ │ │ │ │ │ │ │ │ │ └─ ← [Return] 1911 bytes of code + │ │ │ │ │ │ │ │ │ ├─ [0] VM::label(Node 8: [0x03A6a84cD762D9707A21605b548aaaB891562aAb], "Node 8") + │ │ │ │ │ │ │ │ │ │ └─ ← [Return] + │ │ │ │ │ │ │ │ │ ├─ storage changes: + │ │ │ │ │ │ │ │ │ │ @ 32: 8 → 9 + │ │ │ │ │ │ │ │ │ └─ ← [Return] Node 8: [0x03A6a84cD762D9707A21605b548aaaB891562aAb] + │ │ │ │ │ │ │ │ ├─ emit CreatedChild(childDepth: 8) + │ │ │ │ │ │ │ │ ├─ [..] Node 8::recurseCreate(8, 8) + │ │ │ │ │ │ │ │ │ └─ ← [Return] 8 + │ │ │ │ │ │ │ │ ├─ emit ChildDepth(childDepth: 8) + │ │ │ │ │ │ │ │ ├─ emit Depth(depth: 7) + │ │ │ │ │ │ │ │ └─ ← [Return] 7 + │ │ │ │ │ │ │ ├─ emit ChildDepth(childDepth: 7) + │ │ │ │ │ │ │ ├─ emit Depth(depth: 6) + │ │ │ │ │ │ │ └─ ← [Return] 6 + │ │ │ │ │ │ ├─ emit ChildDepth(childDepth: 6) + │ │ │ │ │ │ ├─ emit Depth(depth: 5) + │ │ │ │ │ │ └─ ← [Return] 5 + │ │ │ │ │ ├─ emit ChildDepth(childDepth: 5) + │ │ │ │ │ ├─ emit Depth(depth: 4) + │ │ │ │ │ └─ ← [Return] 4 + │ │ │ │ ├─ emit ChildDepth(childDepth: 4) + │ │ │ │ ├─ emit Depth(depth: 3) + │ │ │ │ └─ ← [Return] 3 + │ │ │ ├─ emit ChildDepth(childDepth: 3) + │ │ │ ├─ emit Depth(depth: 2) + │ │ │ └─ ← [Return] 2 + │ │ ├─ emit ChildDepth(childDepth: 2) + │ │ ├─ emit Depth(depth: 1) + │ │ └─ ← [Return] 1 + │ ├─ emit ChildDepth(childDepth: 1) + │ ├─ emit Depth(depth: 0) + │ └─ ← [Return] 0 + └─ ← [Stop] + +Suite result: ok. 2 passed; 0 failed; 0 skipped; [ELAPSED] + +Ran 1 test suite [ELAPSED]: 2 tests passed, 0 failed, 0 skipped (2 total tests) + +"#]]); +}); diff --git a/crates/forge/tests/it/cheats.rs b/crates/forge/tests/it/cheats.rs deleted file mode 100644 index 1271f534cdc5d..0000000000000 --- a/crates/forge/tests/it/cheats.rs +++ /dev/null @@ -1,112 +0,0 @@ -//! Forge tests for cheatcodes. -use crate::{ - config::*, - test_helpers::{ - ForgeTestData, ForgeTestProfile, RE_PATH_SEPARATOR, TEST_DATA_DEFAULT, - TEST_DATA_MULTI_VERSION, TEST_DATA_PARIS, - }, -}; -use alloy_primitives::U256; -use foundry_cli::utils::install_crypto_provider; -use foundry_compilers::artifacts::output_selection::ContractOutputSelection; -use foundry_config::{FsPermissions, fs_permissions::PathPermission}; -use foundry_test_utils::{Filter, init_tracing, util::get_compiled}; - -/// Executes all cheat code tests but not fork cheat codes or tests that require isolation mode or -/// specific seed. -async fn test_cheats_local(test_data: &ForgeTestData) { - let mut filter = Filter::new(".*", ".*", &format!(".*cheats{RE_PATH_SEPARATOR}*")) - .exclude_paths("Fork") - .exclude_contracts("(Isolated|WithSeed|StateDiff|GetStorageSlotsTest)"); - - // Exclude FFI tests on Windows because no `echo`, and file tests that expect certain file paths - if cfg!(windows) { - filter = filter.exclude_tests("(Ffi|File|Line|Root)"); - } - - if cfg!(feature = "isolate-by-default") { - filter = filter.exclude_contracts( - "(LastCallGasDefaultTest|MockFunctionTest|WithSeed|StateDiff|GetStorageSlotsTest|RecordAccount)", - ); - } - - let runner = test_data.runner_with(|config| { - config.fs_permissions = FsPermissions::new(vec![PathPermission::read_write("./")]); - }); - - TestConfig::with_filter(runner, filter).run().await; -} - -/// Executes subset of all cheat code tests in isolation mode. -async fn test_cheats_local_isolated(test_data: &ForgeTestData) { - let filter = Filter::new(".*", ".*(Isolated)", &format!(".*cheats{RE_PATH_SEPARATOR}*")) - .exclude_contracts("(StateDiff|GetStorageSlotsTest)"); - - let runner = test_data.runner_with(|config| { - config.isolate = true; - }); - - TestConfig::with_filter(runner, filter).run().await; -} - -/// Executes subset of all cheat code tests using a specific seed. -async fn test_cheats_local_with_seed(test_data: &ForgeTestData) { - let filter = Filter::new(".*", ".*(WithSeed)", &format!(".*cheats{RE_PATH_SEPARATOR}*")); - - let runner = test_data.runner_with(|config| { - config.fuzz.seed = Some(U256::from(100)); - }); - - TestConfig::with_filter(runner, filter).run().await; -} - -#[tokio::test(flavor = "multi_thread")] -async fn test_cheats_local_default() { - test_cheats_local(&TEST_DATA_DEFAULT).await -} - -#[tokio::test(flavor = "multi_thread")] -async fn test_state_diff_storage_layout() { - let test_data = { - let profile = ForgeTestProfile::Default; - install_crypto_provider(); - init_tracing(); - let mut config = profile.config(); - config.extra_output = vec![ContractOutputSelection::StorageLayout]; - let mut project = config.project().unwrap(); - // Compile with StorageLayout - let output = get_compiled(&mut project); - ForgeTestData { project, output, config: config.into(), profile } - }; - let filter = Filter::new( - ".*", - "(StateDiff|GetStorageSlotsTest)", - &format!(".*cheats{RE_PATH_SEPARATOR}*"), - ); - - let runner = test_data.runner_with(|config| { - config.fs_permissions = FsPermissions::new(vec![PathPermission::read_write("./")]); - }); - - TestConfig::with_filter(runner, filter).run().await; -} - -#[tokio::test(flavor = "multi_thread")] -async fn test_cheats_local_default_isolated() { - test_cheats_local_isolated(&TEST_DATA_DEFAULT).await -} - -#[tokio::test(flavor = "multi_thread")] -async fn test_cheats_local_default_with_seed() { - test_cheats_local_with_seed(&TEST_DATA_DEFAULT).await -} - -#[tokio::test(flavor = "multi_thread")] -async fn test_cheats_local_multi_version() { - test_cheats_local(&TEST_DATA_MULTI_VERSION).await -} - -#[tokio::test(flavor = "multi_thread")] -async fn test_cheats_local_paris() { - test_cheats_local(&TEST_DATA_PARIS).await -} diff --git a/crates/forge/tests/it/config.rs b/crates/forge/tests/it/config.rs deleted file mode 100644 index b028b45005b8d..0000000000000 --- a/crates/forge/tests/it/config.rs +++ /dev/null @@ -1,170 +0,0 @@ -//! Test config. - -use forge::{ - MultiContractRunner, - result::{SuiteResult, TestStatus}, -}; -use foundry_evm::{ - decode::decode_console_logs, - traces::{CallTraceDecoderBuilder, decode_trace_arena, render_trace_arena}, -}; -use foundry_test_utils::{Filter, init_tracing}; -use futures::future::join_all; -use itertools::Itertools; -use revm::primitives::hardfork::SpecId; -use std::collections::BTreeMap; - -/// How to execute a test run. -pub struct TestConfig { - pub runner: MultiContractRunner, - pub should_fail: bool, - pub filter: Filter, -} - -impl TestConfig { - pub fn new(runner: MultiContractRunner) -> Self { - Self::with_filter(runner, Filter::matches_all()) - } - - pub fn with_filter(runner: MultiContractRunner, filter: Filter) -> Self { - init_tracing(); - Self { runner, should_fail: false, filter } - } - - pub fn spec_id(mut self, spec: SpecId) -> Self { - self.runner.spec_id = spec; - self - } - - pub fn should_fail(self) -> Self { - self.set_should_fail(true) - } - - pub fn set_should_fail(mut self, should_fail: bool) -> Self { - self.should_fail = should_fail; - self - } - - /// Executes the test runner - pub fn test(&mut self) -> eyre::Result> { - self.runner.test_collect(&self.filter) - } - - pub async fn run(&mut self) { - self.try_run().await.unwrap() - } - - /// Executes the test case - /// - /// Returns an error if - /// * filter matched 0 test cases - /// * a test results deviates from the configured `should_fail` setting - pub async fn try_run(&mut self) -> eyre::Result<()> { - let suite_result = self.test()?; - if suite_result.is_empty() { - eyre::bail!("empty test result"); - } - for (_, SuiteResult { test_results, .. }) in suite_result { - for (test_name, mut result) in test_results { - if self.should_fail && (result.status == TestStatus::Success) - || !self.should_fail && (result.status == TestStatus::Failure) - { - let logs = decode_console_logs(&result.logs); - let outcome = if self.should_fail { "fail" } else { "pass" }; - let call_trace_decoder = CallTraceDecoderBuilder::default() - .with_known_contracts(&self.runner.known_contracts) - .build(); - let decoded_traces = join_all(result.traces.iter_mut().map(|(_, arena)| { - let decoder = &call_trace_decoder; - async move { - decode_trace_arena(arena, decoder).await; - render_trace_arena(arena) - } - })) - .await - .into_iter() - .collect::>(); - eyre::bail!( - "Test {} did not {} as expected.\nReason: {:?}\nLogs:\n{}\n\nTraces:\n{}", - test_name, - outcome, - result.reason, - logs.join("\n"), - decoded_traces.into_iter().format("\n"), - ) - } - } - } - - Ok(()) - } -} - -/// A helper to assert the outcome of multiple tests with helpful assert messages -#[track_caller] -#[expect(clippy::type_complexity)] -pub fn assert_multiple( - actuals: &BTreeMap, - expecteds: BTreeMap< - &str, - Vec<(&str, bool, Option, Option>, Option)>, - >, -) { - assert_eq!(actuals.len(), expecteds.len(), "We did not run as many contracts as we expected"); - for (contract_name, tests) in &expecteds { - assert!( - actuals.contains_key(*contract_name), - "We did not run the contract {contract_name}" - ); - - assert_eq!( - actuals[*contract_name].len(), - expecteds[contract_name].len(), - "We did not run as many test functions as we expected for {contract_name}" - ); - for (test_name, should_pass, reason, expected_logs, expected_warning_count) in tests { - let logs = &decode_console_logs(&actuals[*contract_name].test_results[*test_name].logs); - - let warnings_count = &actuals[*contract_name].warnings.len(); - - if *should_pass { - assert!( - actuals[*contract_name].test_results[*test_name].status == TestStatus::Success, - "Test {} did not pass as expected.\nReason: {:?}\nLogs:\n{}", - test_name, - actuals[*contract_name].test_results[*test_name].reason, - logs.join("\n") - ); - } else { - assert!( - actuals[*contract_name].test_results[*test_name].status == TestStatus::Failure, - "Test {} did not fail as expected.\nLogs:\n{}", - test_name, - logs.join("\n") - ); - assert_eq!( - actuals[*contract_name].test_results[*test_name].reason, *reason, - "Failure reason for test {test_name} did not match what we expected." - ); - } - - if let Some(expected_logs) = expected_logs { - assert_eq!( - logs, - expected_logs, - "Logs did not match for test {}.\nExpected:\n{}\n\nGot:\n{}", - test_name, - expected_logs.join("\n"), - logs.join("\n") - ); - } - - if let Some(expected_warning_count) = expected_warning_count { - assert_eq!( - warnings_count, expected_warning_count, - "Test {test_name} did not pass as expected. Expected:\n{expected_warning_count}Got:\n{warnings_count}" - ); - } - } - } -} diff --git a/crates/forge/tests/it/core.rs b/crates/forge/tests/it/core.rs deleted file mode 100644 index 161f4db363c20..0000000000000 --- a/crates/forge/tests/it/core.rs +++ /dev/null @@ -1,829 +0,0 @@ -//! Forge tests for core functionality. - -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; -use std::{collections::BTreeMap, env}; - -#[tokio::test(flavor = "multi_thread")] -async fn test_core() { - let filter = Filter::new(".*", ".*", ".*core"); - let mut runner = TEST_DATA_DEFAULT.runner(); - let results = runner.test_collect(&filter).unwrap(); - - assert_multiple( - &results, - BTreeMap::from([ - ( - "default/core/Reverting.t.sol:RevertingTest", - vec![("testRevert()", true, None, None, None)], - ), - ( - "default/core/SetupConsistency.t.sol:SetupConsistencyCheck", - vec![ - ("testAdd()", true, None, None, None), - ("testMultiply()", true, None, None, None), - ], - ), - ( - "default/core/ContractEnvironment.t.sol:ContractEnvironmentTest", - vec![ - ("testAddresses()", true, None, None, None), - ("testEnvironment()", true, None, None, None), - ], - ), - ( - "default/core/PaymentFailure.t.sol:PaymentFailureTest", - vec![("testCantPay()", false, Some("EvmError: Revert".to_string()), None, None)], - ), - ( - "default/core/Abstract.t.sol:AbstractTest", - vec![("testSomething()", true, None, None, None)], - ), - ( - "default/core/FailingTestAfterFailedSetup.t.sol:FailingTestAfterFailedSetupTest", - vec![("setUp()", false, Some("execution error".to_string()), None, None)], - ), - ( - "default/core/BadSigAfterInvariant.t.sol:BadSigAfterInvariant", - vec![("testShouldPassWithWarning()", true, None, None, None)], - ), - ( - "default/core/LegacyAssertions.t.sol:NoAssertionsRevertTest", - vec![( - "testMultipleAssertFailures()", - false, - Some("assertion failed: 1 != 2".to_string()), - None, - None, - )], - ), - ( - "default/core/LegacyAssertions.t.sol:LegacyAssertionsTest", - vec![ - ("testFlagNotSetSuccess()", true, None, None, None), - ("testFlagSetFailure()", true, None, None, None), - ], - ), - ]), - ); -} - -#[tokio::test(flavor = "multi_thread")] -async fn test_linking() { - let filter = Filter::new(".*", ".*", ".*linking"); - let mut runner = TEST_DATA_DEFAULT.runner(); - let results = runner.test_collect(&filter).unwrap(); - - assert_multiple( - &results, - BTreeMap::from([ - ( - "default/linking/simple/Simple.t.sol:SimpleLibraryLinkingTest", - vec![("testCall()", true, None, None, None)], - ), - ( - "default/linking/nested/Nested.t.sol:NestedLibraryLinkingTest", - vec![ - ("testDirect()", true, None, None, None), - ("testNested()", true, None, None, None), - ], - ), - ( - "default/linking/duplicate/Duplicate.t.sol:DuplicateLibraryLinkingTest", - vec![ - ("testA()", true, None, None, None), - ("testB()", true, None, None, None), - ("testC()", true, None, None, None), - ("testD()", true, None, None, None), - ("testE()", true, None, None, None), - ], - ), - ]), - ); -} - -#[tokio::test(flavor = "multi_thread")] -async fn test_logs() { - let filter = Filter::new(".*", ".*", ".*logs"); - let mut runner = TEST_DATA_DEFAULT.runner(); - let results = runner.test_collect(&filter).unwrap(); - - assert_multiple( - &results, - BTreeMap::from([ - ( - "default/logs/DebugLogs.t.sol:DebugLogsTest", - vec![ - ("test1()", true, None, Some(vec!["0".into(), "1".into(), "2".into()]), None), - ("test2()", true, None, Some(vec!["0".into(), "1".into(), "3".into()]), None), - ( - "testRevertIfWithRequire()", - true, - None, - Some(vec!["0".into(), "1".into(), "5".into()]), - None, - ), - ( - "testRevertIfWithRevert()", - true, - None, - Some(vec!["0".into(), "1".into(), "4".into(), "100".into()]), - None, - ), - ( - "testLog()", - true, - None, - Some(vec!["0".into(), "1".into(), "Error: Assertion Failed".into()]), - None, - ), - ( - "testLogs()", - true, - None, - Some(vec!["0".into(), "1".into(), "0x61626364".into()]), - None, - ), - ( - "testLogAddress()", - true, - None, - Some(vec![ - "0".into(), - "1".into(), - "0x0000000000000000000000000000000000000001".into(), - ]), - None, - ), - ( - "testLogBytes32()", - true, - None, - Some(vec![ - "0".into(), - "1".into(), - "0x6162636400000000000000000000000000000000000000000000000000000000" - .into(), - ]), - None, - ), - ( - "testLogInt()", - true, - None, - Some(vec!["0".into(), "1".into(), "-31337".into()]), - None, - ), - ( - "testLogBytes()", - true, - None, - Some(vec!["0".into(), "1".into(), "0x61626364".into()]), - None, - ), - ( - "testLogString()", - true, - None, - Some(vec!["0".into(), "1".into(), "here".into()]), - None, - ), - ( - "testLogNamedAddress()", - true, - None, - Some(vec![ - "0".into(), - "1".into(), - "address: 0x0000000000000000000000000000000000000001".into(), - ]), - None, - ), - ( - "testLogNamedBytes32()", - true, - None, - Some(vec![ - "0".into(), - "1".into(), - "abcd: 0x6162636400000000000000000000000000000000000000000000000000000000" - .into(), - ]), - None, - ), - ( - "testLogNamedDecimalInt()", - true, - None, - Some(vec!["0".into(), "1".into(), "amount: -0.000000000000031337".into()]), - None, - ), - ( - "testLogNamedDecimalUint()", - true, - None, - Some(vec!["0".into(), "1".into(), "amount: 1.000000000000000000".into()]), - None, - ), - ( - "testLogNamedInt()", - true, - None, - Some(vec!["0".into(), "1".into(), "amount: -31337".into()]), - None, - ), - ( - "testLogNamedUint()", - true, - None, - Some(vec!["0".into(), "1".into(), "amount: 1000000000000000000".into()]), - None, - ), - ( - "testLogNamedBytes()", - true, - None, - Some(vec!["0".into(), "1".into(), "abcd: 0x61626364".into()]), - None, - ), - ( - "testLogNamedString()", - true, - None, - Some(vec!["0".into(), "1".into(), "key: val".into()]), - None, - ), - ], - ), - ( - "default/logs/HardhatLogs.t.sol:HardhatLogsTest", - vec![ - ( - "testInts()", - true, - None, - Some(vec![ - "constructor".into(), - "0".into(), - "1".into(), - "2".into(), - "3".into(), - ]), - None, - ), - ( - "testMisc()", - true, - None, - Some(vec![ - "constructor".into(), - "testMisc 0x0000000000000000000000000000000000000001".into(), - "testMisc 42".into(), - ]), - None, - ), - ( - "testStrings()", - true, - None, - Some(vec!["constructor".into(), "testStrings".into()]), - None, - ), - ( - "testConsoleLog()", - true, - None, - Some(vec!["constructor".into(), "test".into()]), - None, - ), - ( - "testLogInt()", - true, - None, - Some(vec!["constructor".into(), "-31337".into()]), - None, - ), - ( - "testLogUint()", - true, - None, - Some(vec!["constructor".into(), "1".into()]), - None, - ), - ( - "testLogString()", - true, - None, - Some(vec!["constructor".into(), "test".into()]), - None, - ), - ( - "testLogBool()", - true, - None, - Some(vec!["constructor".into(), "false".into()]), - None, - ), - ( - "testLogAddress()", - true, - None, - Some(vec![ - "constructor".into(), - "0x0000000000000000000000000000000000000001".into(), - ]), - None, - ), - ( - "testLogBytes()", - true, - None, - Some(vec!["constructor".into(), "0x61".into()]), - None, - ), - ( - "testLogBytes1()", - true, - None, - Some(vec!["constructor".into(), "0x61".into()]), - None, - ), - ( - "testLogBytes2()", - true, - None, - Some(vec!["constructor".into(), "0x6100".into()]), - None, - ), - ( - "testLogBytes3()", - true, - None, - Some(vec!["constructor".into(), "0x610000".into()]), - None, - ), - ( - "testLogBytes4()", - true, - None, - Some(vec!["constructor".into(), "0x61000000".into()]), - None, - ), - ( - "testLogBytes5()", - true, - None, - Some(vec!["constructor".into(), "0x6100000000".into()]), - None, - ), - ( - "testLogBytes6()", - true, - None, - Some(vec!["constructor".into(), "0x610000000000".into()]), - None, - ), - ( - "testLogBytes7()", - true, - None, - Some(vec!["constructor".into(), "0x61000000000000".into()]), - None, - ), - ( - "testLogBytes8()", - true, - None, - Some(vec!["constructor".into(), "0x6100000000000000".into()]), - None, - ), - ( - "testLogBytes9()", - true, - None, - Some(vec!["constructor".into(), "0x610000000000000000".into()]), - None, - ), - ( - "testLogBytes10()", - true, - None, - Some(vec!["constructor".into(), "0x61000000000000000000".into()]), - None, - ), - ( - "testLogBytes11()", - true, - None, - Some(vec!["constructor".into(), "0x6100000000000000000000".into()]), - None, - ), - ( - "testLogBytes12()", - true, - None, - Some(vec!["constructor".into(), "0x610000000000000000000000".into()]), - None, - ), - ( - "testLogBytes13()", - true, - None, - Some(vec!["constructor".into(), "0x61000000000000000000000000".into()]), - None, - ), - ( - "testLogBytes14()", - true, - None, - Some(vec!["constructor".into(), "0x6100000000000000000000000000".into()]), - None, - ), - ( - "testLogBytes15()", - true, - None, - Some(vec!["constructor".into(), "0x610000000000000000000000000000".into()]), - None, - ), - ( - "testLogBytes16()", - true, - None, - Some(vec![ - "constructor".into(), - "0x61000000000000000000000000000000".into(), - ]), - None, - ), - ( - "testLogBytes17()", - true, - None, - Some(vec![ - "constructor".into(), - "0x6100000000000000000000000000000000".into(), - ]), - None, - ), - ( - "testLogBytes18()", - true, - None, - Some(vec![ - "constructor".into(), - "0x610000000000000000000000000000000000".into(), - ]), - None, - ), - ( - "testLogBytes19()", - true, - None, - Some(vec![ - "constructor".into(), - "0x61000000000000000000000000000000000000".into(), - ]), - None, - ), - ( - "testLogBytes20()", - true, - None, - Some(vec![ - "constructor".into(), - "0x6100000000000000000000000000000000000000".into(), - ]), - None, - ), - ( - "testLogBytes21()", - true, - None, - Some(vec![ - "constructor".into(), - "0x610000000000000000000000000000000000000000".into(), - ]), - None, - ), - ( - "testLogBytes22()", - true, - None, - Some(vec![ - "constructor".into(), - "0x61000000000000000000000000000000000000000000".into(), - ]), - None, - ), - ( - "testLogBytes23()", - true, - None, - Some(vec![ - "constructor".into(), - "0x6100000000000000000000000000000000000000000000".into(), - ]), - None, - ), - ( - "testLogBytes24()", - true, - None, - Some(vec![ - "constructor".into(), - "0x610000000000000000000000000000000000000000000000".into(), - ]), - None, - ), - ( - "testLogBytes25()", - true, - None, - Some(vec![ - "constructor".into(), - "0x61000000000000000000000000000000000000000000000000".into(), - ]), - None, - ), - ( - "testLogBytes26()", - true, - None, - Some(vec![ - "constructor".into(), - "0x6100000000000000000000000000000000000000000000000000".into(), - ]), - None, - ), - ( - "testLogBytes27()", - true, - None, - Some(vec![ - "constructor".into(), - "0x610000000000000000000000000000000000000000000000000000".into(), - ]), - None, - ), - ( - "testLogBytes28()", - true, - None, - Some(vec![ - "constructor".into(), - "0x61000000000000000000000000000000000000000000000000000000".into(), - ]), - None, - ), - ( - "testLogBytes29()", - true, - None, - Some(vec![ - "constructor".into(), - "0x6100000000000000000000000000000000000000000000000000000000".into(), - ]), - None, - ), - ( - "testLogBytes30()", - true, - None, - Some(vec![ - "constructor".into(), - "0x610000000000000000000000000000000000000000000000000000000000".into(), - ]), - None, - ), - ( - "testLogBytes31()", - true, - None, - Some(vec![ - "constructor".into(), - "0x61000000000000000000000000000000000000000000000000000000000000" - .into(), - ]), - None, - ), - ( - "testLogBytes32()", - true, - None, - Some(vec![ - "constructor".into(), - "0x6100000000000000000000000000000000000000000000000000000000000000" - .into(), - ]), - None, - ), - ( - "testConsoleLogUint()", - true, - None, - Some(vec!["constructor".into(), "1".into()]), - None, - ), - ( - "testConsoleLogString()", - true, - None, - Some(vec!["constructor".into(), "test".into()]), - None, - ), - ( - "testConsoleLogBool()", - true, - None, - Some(vec!["constructor".into(), "false".into()]), - None, - ), - ( - "testConsoleLogAddress()", - true, - None, - Some(vec![ - "constructor".into(), - "0x0000000000000000000000000000000000000001".into(), - ]), - None, - ), - ( - "testConsoleLogFormatString()", - true, - None, - Some(vec!["constructor".into(), "formatted log str=test".into()]), - None, - ), - ( - "testConsoleLogFormatUint()", - true, - None, - Some(vec!["constructor".into(), "formatted log uint=1".into()]), - None, - ), - ( - "testConsoleLogFormatAddress()", - true, - None, - Some(vec![ - "constructor".into(), - "formatted log addr=0x0000000000000000000000000000000000000001".into(), - ]), - None, - ), - ( - "testConsoleLogFormatMulti()", - true, - None, - Some(vec!["constructor".into(), "formatted log str=test uint=1".into()]), - None, - ), - ( - "testConsoleLogFormatEscape()", - true, - None, - Some(vec!["constructor".into(), "formatted log % test".into()]), - None, - ), - ( - "testConsoleLogFormatSpill()", - true, - None, - Some(vec!["constructor".into(), "formatted log test 1".into()]), - None, - ), - ], - ), - ]), - ); -} - -#[tokio::test(flavor = "multi_thread")] -async fn test_env_vars() { - let env_var_key = "_foundryCheatcodeSetEnvTestKey"; - let env_var_val = "_foundryCheatcodeSetEnvTestVal"; - unsafe { - env::remove_var(env_var_key); - } - - let filter = Filter::new("testSetEnv", ".*", ".*"); - let mut runner = TEST_DATA_DEFAULT.runner(); - let _ = runner.test_collect(&filter); - - assert_eq!(env::var(env_var_key).unwrap(), env_var_val); -} - -#[tokio::test(flavor = "multi_thread")] -async fn test_doesnt_run_abstract_contract() { - let filter = Filter::new(".*", ".*", ".*Abstract.t.sol".to_string().as_str()); - let mut runner = TEST_DATA_DEFAULT.runner(); - let results = runner.test_collect(&filter).unwrap(); - assert!(!results.contains_key("default/core/Abstract.t.sol:AbstractTestBase")); - assert!(results.contains_key("default/core/Abstract.t.sol:AbstractTest")); -} - -#[tokio::test(flavor = "multi_thread")] -async fn test_trace() { - let filter = Filter::new(".*", ".*", ".*trace"); - let mut runner = TEST_DATA_DEFAULT.tracing_runner(); - let suite_result = runner.test_collect(&filter).unwrap(); - - // TODO: This trace test is very basic - it is probably a good candidate for snapshot - // testing. - for (_, SuiteResult { test_results, .. }) in suite_result { - for (test_name, result) in test_results { - let deployment_traces = - result.traces.iter().filter(|(kind, _)| *kind == TraceKind::Deployment); - let setup_traces = result.traces.iter().filter(|(kind, _)| *kind == TraceKind::Setup); - let execution_traces = - result.traces.iter().filter(|(kind, _)| *kind == TraceKind::Execution); - - assert_eq!( - deployment_traces.count(), - 14, - "Test {test_name} did not have exactly 14 deployment traces." - ); - assert!(setup_traces.count() <= 1, "Test {test_name} had more than 1 setup trace."); - assert_eq!( - execution_traces.count(), - 1, - "Test {test_name} did not have exactly 1 execution trace." - ); - } - } -} - -#[tokio::test(flavor = "multi_thread")] -async fn test_assertions_revert_false() { - let filter = Filter::new(".*", ".*NoAssertionsRevertTest", ".*"); - let mut runner = TEST_DATA_DEFAULT.runner_with(|config| { - config.assertions_revert = false; - }); - let results = runner.test_collect(&filter).unwrap(); - - assert_multiple( - &results, - BTreeMap::from([( - "default/core/LegacyAssertions.t.sol:NoAssertionsRevertTest", - vec![( - "testMultipleAssertFailures()", - false, - None, - Some(vec![ - "assertion failed: 1 != 2".to_string(), - "assertion failed: 5 >= 4".to_string(), - ]), - None, - )], - )]), - ); -} - -#[tokio::test(flavor = "multi_thread")] -async fn test_legacy_assertions() { - let filter = Filter::new(".*", ".*LegacyAssertions", ".*"); - let mut runner = TEST_DATA_DEFAULT.runner_with(|config| { - config.legacy_assertions = true; - }); - let results = runner.test_collect(&filter).unwrap(); - - assert_multiple( - &results, - BTreeMap::from([( - "default/core/LegacyAssertions.t.sol:LegacyAssertionsTest", - vec![ - ("testFlagNotSetSuccess()", true, None, None, None), - ("testFlagSetFailure()", false, None, None, None), - ], - )]), - ); -} - -/// 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).unwrap(); - - 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 deleted file mode 100644 index 92038ead6df9f..0000000000000 --- a/crates/forge/tests/it/fork.rs +++ /dev/null @@ -1,129 +0,0 @@ -//! Forge forking tests. - -use crate::{ - config::*, - test_helpers::{RE_PATH_SEPARATOR, TEST_DATA_DEFAULT, TEST_DATA_PARIS}, -}; -use alloy_chains::Chain; -use forge::result::SuiteResult; -use foundry_config::{Config, FsPermissions, fs_permissions::PathPermission}; -use foundry_test_utils::Filter; -use std::fs; - -/// Executes reverting fork test -#[tokio::test(flavor = "multi_thread")] -async fn test_cheats_fork_revert() { - let filter = Filter::new( - "testNonExistingContractRevert", - ".*", - &format!(".*cheats{RE_PATH_SEPARATOR}Fork"), - ); - let mut runner = TEST_DATA_DEFAULT.runner(); - let suite_result = runner.test_collect(&filter).unwrap(); - assert_eq!(suite_result.len(), 1); - - for (_, SuiteResult { test_results, .. }) in suite_result { - for (_, result) in test_results { - assert_eq!( - result.reason.unwrap(), - "Contract 0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f does not exist on active fork with id `1`\n But exists on non active forks: `[0]`" - ); - } - } -} - -/// Executes all non-reverting fork cheatcodes -#[tokio::test(flavor = "multi_thread")] -async fn test_cheats_fork() { - let runner = TEST_DATA_PARIS.runner_with(|config| { - config.fs_permissions = FsPermissions::new(vec![PathPermission::read("./fixtures")]); - }); - let filter = Filter::new(".*", ".*", &format!(".*cheats{RE_PATH_SEPARATOR}Fork")) - .exclude_tests(".*Revert"); - TestConfig::with_filter(runner, filter).run().await; -} - -/// Executes eth_getLogs cheatcode -#[tokio::test(flavor = "multi_thread")] -async fn test_get_logs_fork() { - let runner = TEST_DATA_DEFAULT.runner_with(|config| { - config.fs_permissions = FsPermissions::new(vec![PathPermission::read("./fixtures")]); - }); - let filter = Filter::new("testEthGetLogs", ".*", &format!(".*cheats{RE_PATH_SEPARATOR}Fork")) - .exclude_tests(".*Revert"); - TestConfig::with_filter(runner, filter).run().await; -} - -/// Executes rpc cheatcode -#[tokio::test(flavor = "multi_thread")] -async fn test_rpc_fork() { - let runner = TEST_DATA_DEFAULT.runner_with(|config| { - config.fs_permissions = FsPermissions::new(vec![PathPermission::read("./fixtures")]); - }); - let filter = Filter::new("testRpc", ".*", &format!(".*cheats{RE_PATH_SEPARATOR}Fork")) - .exclude_tests(".*Revert"); - TestConfig::with_filter(runner, filter).run().await; -} - -/// Tests that we can launch in forking mode -#[tokio::test(flavor = "multi_thread")] -async fn test_launch_fork() { - let rpc_url = foundry_test_utils::rpc::next_http_archive_rpc_url(); - let runner = TEST_DATA_DEFAULT.forked_runner(&rpc_url).await; - let filter = Filter::new(".*", ".*", &format!(".*fork{RE_PATH_SEPARATOR}Launch")); - TestConfig::with_filter(runner, filter).run().await; -} - -/// Smoke test that forking workings with websockets -#[tokio::test(flavor = "multi_thread")] -async fn test_launch_fork_ws() { - let rpc_url = foundry_test_utils::rpc::next_ws_archive_rpc_url(); - let runner = TEST_DATA_DEFAULT.forked_runner(&rpc_url).await; - let filter = Filter::new(".*", ".*", &format!(".*fork{RE_PATH_SEPARATOR}Launch")); - TestConfig::with_filter(runner, filter).run().await; -} - -/// Tests that we can transact transactions in forking mode -#[tokio::test(flavor = "multi_thread")] -async fn test_transact_fork() { - let runner = TEST_DATA_PARIS.runner(); - let filter = Filter::new(".*", ".*", &format!(".*fork{RE_PATH_SEPARATOR}Transact")); - TestConfig::with_filter(runner, filter).run().await; -} - -/// Tests that we can create the same fork (provider,block) concurrently in different tests -#[tokio::test(flavor = "multi_thread")] -async fn test_create_same_fork() { - let runner = TEST_DATA_DEFAULT.runner(); - let filter = Filter::new(".*", ".*", &format!(".*fork{RE_PATH_SEPARATOR}ForkSame")); - TestConfig::with_filter(runner, filter).run().await; -} - -/// Test that `no_storage_caching` config is properly applied -#[tokio::test(flavor = "multi_thread")] -async fn test_storage_caching_config() { - let filter = - Filter::new("testStorageCaching", ".*", &format!(".*cheats{RE_PATH_SEPARATOR}Fork")) - .exclude_tests(".*Revert"); - - let runner = TEST_DATA_DEFAULT.runner_with(|config| { - config.no_storage_caching = true; - }); - - // no_storage_caching set to true: storage should not be cached - TestConfig::with_filter(runner, filter.clone()).run().await; - let cache_dir = Config::foundry_block_cache_dir(Chain::mainnet(), 19800000).unwrap(); - let _ = fs::remove_file(cache_dir); - - let runner = TEST_DATA_DEFAULT.runner_with(|config| { - config.no_storage_caching = false; - }); - TestConfig::with_filter(runner, filter).run().await; - - // no_storage_caching set to false: storage should be cached - let cache_dir = Config::foundry_block_cache_dir(Chain::mainnet(), 19800000).unwrap(); - assert!(cache_dir.exists()); - - // cleanup cached storage so subsequent tests does not fail - let _ = fs::remove_file(cache_dir); -} diff --git a/crates/forge/tests/it/fs.rs b/crates/forge/tests/it/fs.rs deleted file mode 100644 index 3e9fb1f4dad82..0000000000000 --- a/crates/forge/tests/it/fs.rs +++ /dev/null @@ -1,23 +0,0 @@ -//! Filesystem tests. - -use crate::{config::*, test_helpers::TEST_DATA_DEFAULT}; -use foundry_config::{FsPermissions, fs_permissions::PathPermission}; -use foundry_test_utils::Filter; - -#[tokio::test(flavor = "multi_thread")] -async fn test_fs_disabled() { - let runner = TEST_DATA_DEFAULT.runner_with(|config| { - config.fs_permissions = FsPermissions::new(vec![PathPermission::none("./")]); - }); - let filter = Filter::new(".*", ".*", ".*fs/Disabled"); - TestConfig::with_filter(runner, filter).run().await; -} - -#[tokio::test(flavor = "multi_thread")] -async fn test_fs_default() { - let runner = TEST_DATA_DEFAULT.runner_with(|config| { - config.fs_permissions = FsPermissions::new(vec![PathPermission::read("./fixtures")]); - }); - let filter = Filter::new(".*", ".*", ".*fs/Default"); - TestConfig::with_filter(runner, filter).run().await; -} diff --git a/crates/forge/tests/it/fuzz.rs b/crates/forge/tests/it/fuzz.rs deleted file mode 100644 index 616b19a17f805..0000000000000 --- a/crates/forge/tests/it/fuzz.rs +++ /dev/null @@ -1,496 +0,0 @@ -//! Fuzz tests. - -use crate::{config::*, test_helpers::TEST_DATA_DEFAULT}; -use alloy_primitives::{Bytes, U256}; -use forge::{ - decode::decode_console_logs, - fuzz::CounterExample, - result::{SuiteResult, TestStatus}, -}; -use foundry_test_utils::{Filter, forgetest_init, str}; -use std::collections::BTreeMap; - -#[tokio::test(flavor = "multi_thread")] -async fn test_fuzz() { - let filter = Filter::new(".*", ".*", ".*fuzz/") - .exclude_tests(r"invariantCounter|testIncrement\(address\)|testNeedle\(uint256\)|testSuccessChecker\(uint256\)|testSuccessChecker2\(int256\)|testSuccessChecker3\(uint32\)|testStorageOwner\(address\)|testImmutableOwner\(address\)") - .exclude_paths("invariant"); - let mut runner = TEST_DATA_DEFAULT.runner(); - let suite_result = runner.test_collect(&filter).unwrap(); - - assert!(!suite_result.is_empty()); - - for (_, SuiteResult { test_results, .. }) in suite_result { - for (test_name, result) in test_results { - match test_name.as_str() { - "testPositive(uint256)" - | "testPositive(int256)" - | "testSuccessfulFuzz(uint128,uint128)" - | "testToStringFuzz(bytes32)" => assert_eq!( - result.status, - TestStatus::Success, - "Test {} did not pass as expected.\nReason: {:?}\nLogs:\n{}", - test_name, - result.reason, - decode_console_logs(&result.logs).join("\n") - ), - _ => assert_eq!( - result.status, - TestStatus::Failure, - "Test {} did not fail as expected.\nReason: {:?}\nLogs:\n{}", - test_name, - result.reason, - decode_console_logs(&result.logs).join("\n") - ), - } - } - } -} - -#[tokio::test(flavor = "multi_thread")] -async fn test_successful_fuzz_cases() { - let filter = Filter::new(".*", ".*", ".*fuzz/FuzzPositive") - .exclude_tests(r"invariantCounter|testIncrement\(address\)|testNeedle\(uint256\)") - .exclude_paths("invariant"); - let mut runner = TEST_DATA_DEFAULT.runner(); - let suite_result = runner.test_collect(&filter).unwrap(); - - assert!(!suite_result.is_empty()); - - for (_, SuiteResult { test_results, .. }) in suite_result { - for (test_name, result) in test_results { - match test_name.as_str() { - "testSuccessChecker(uint256)" - | "testSuccessChecker2(int256)" - | "testSuccessChecker3(uint32)" => assert_eq!( - result.status, - TestStatus::Success, - "Test {} did not pass as expected.\nReason: {:?}\nLogs:\n{}", - test_name, - result.reason, - decode_console_logs(&result.logs).join("\n") - ), - _ => {} - } - } - } -} - -/// Test that showcases PUSH collection on normal fuzzing. Ignored until we collect them in a -/// smarter way. -#[tokio::test(flavor = "multi_thread")] -#[ignore] -async fn test_fuzz_collection() { - let filter = Filter::new(".*", ".*", ".*fuzz/FuzzCollection.t.sol"); - let mut runner = TEST_DATA_DEFAULT.runner_with(|config| { - config.invariant.depth = 100; - config.invariant.runs = 1000; - config.fuzz.runs = 1000; - config.fuzz.seed = Some(U256::from(6u32)); - }); - let results = runner.test_collect(&filter).unwrap(); - - assert_multiple( - &results, - BTreeMap::from([( - "default/fuzz/FuzzCollection.t.sol:SampleContractTest", - vec![ - ("invariantCounter", false, Some("broken counter.".into()), None, None), - ( - "testIncrement(address)", - false, - Some("Call did not revert as expected".into()), - None, - None, - ), - ("testNeedle(uint256)", false, Some("needle found.".into()), None, None), - ], - )]), - ); -} - -#[tokio::test(flavor = "multi_thread")] -async fn test_persist_fuzz_failure() { - let filter = Filter::new(".*", ".*", ".*fuzz/FuzzFailurePersist.t.sol"); - - macro_rules! run_fail { - () => { run_fail!(|config| {}) }; - (|$config:ident| $e:expr) => {{ - let mut runner = TEST_DATA_DEFAULT.runner_with(|$config| { - $config.fuzz.runs = 1000; - $e - }); - runner - .test_collect(&filter) - .unwrap() - .get("default/fuzz/FuzzFailurePersist.t.sol:FuzzFailurePersistTest") - .unwrap() - .test_results - .get("test_persist_fuzzed_failure(uint256,int256,address,bool,string,(address,uint256),address[])") - .unwrap() - .counterexample - .clone() - }}; - } - - // record initial counterexample calldata - let initial_counterexample = run_fail!(); - let initial_calldata = match initial_counterexample { - Some(CounterExample::Single(counterexample)) => counterexample.calldata, - _ => Bytes::new(), - }; - - // run several times and compare counterexamples calldata - for i in 0..10 { - let new_calldata = match run_fail!() { - Some(CounterExample::Single(counterexample)) => counterexample.calldata, - _ => Bytes::new(), - }; - // calldata should be the same with the initial one - assert_eq!(initial_calldata, new_calldata, "run {i}"); - } - - // write new failure in different dir. - let persist_dir = tempfile::tempdir().unwrap().keep(); - let new_calldata = match run_fail!(|config| config.fuzz.failure_persist_dir = Some(persist_dir)) - { - Some(CounterExample::Single(counterexample)) => counterexample.calldata, - _ => Bytes::new(), - }; - // empty file is used to load failure so new calldata is generated - assert_ne!(initial_calldata, new_calldata); -} - -forgetest_init!(test_can_scrape_bytecode, |prj, cmd| { - prj.update_config(|config| config.optimizer = Some(true)); - prj.add_source( - "FuzzerDict.sol", - r#" -// https://github.com/foundry-rs/foundry/issues/1168 -contract FuzzerDict { - // Immutables should get added to the dictionary. - address public immutable immutableOwner; - // Regular storage variables should also get added to the dictionary. - address public storageOwner; - - constructor(address _immutableOwner, address _storageOwner) { - immutableOwner = _immutableOwner; - storageOwner = _storageOwner; - } -} - "#, - ); - - prj.add_test( - "FuzzerDictTest.t.sol", - r#" -import {Test} from "forge-std/Test.sol"; -import "src/FuzzerDict.sol"; - -contract FuzzerDictTest is Test { - FuzzerDict fuzzerDict; - - function setUp() public { - fuzzerDict = new FuzzerDict(address(100), address(200)); - } - - /// forge-config: default.fuzz.runs = 2000 - function testImmutableOwner(address who) public { - assertTrue(who != fuzzerDict.immutableOwner()); - } - - /// forge-config: default.fuzz.runs = 2000 - function testStorageOwner(address who) public { - assertTrue(who != fuzzerDict.storageOwner()); - } -} - "#, - ); - - // Test that immutable address is used as fuzzed input, causing test to fail. - 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", "119", "--mt", "testStorageOwner"]) - .assert_failure(); -}); - -// tests that inline max-test-rejects config is properly applied -forgetest_init!(test_inline_max_test_rejects, |prj, cmd| { - prj.wipe_contracts(); - - prj.add_test( - "Contract.t.sol", - r#" -import {Test} from "forge-std/Test.sol"; - -contract InlineMaxRejectsTest is Test { - /// forge-config: default.fuzz.max-test-rejects = 1 - function test_fuzz_bound(uint256 a) public { - vm.assume(false); - } -} - "#, - ); - - cmd.args(["test"]).assert_failure().stdout_eq(str![[r#" -... -[FAIL: `vm.assume` rejected too many inputs (1 allowed)] test_fuzz_bound(uint256) (runs: 0, [AVG_GAS]) -... -"#]]); -}); - -// Tests that test timeout config is properly applied. -// If test doesn't timeout after one second, then test will fail with `rejected too many inputs`. -forgetest_init!(test_fuzz_timeout, |prj, cmd| { - prj.wipe_contracts(); - - prj.add_test( - "Contract.t.sol", - r#" -import {Test} from "forge-std/Test.sol"; - -contract FuzzTimeoutTest is Test { - /// forge-config: default.fuzz.max-test-rejects = 50000 - /// forge-config: default.fuzz.timeout = 1 - function test_fuzz_bound(uint256 a) public pure { - vm.assume(a == 0); - } -} - "#, - ); - - cmd.args(["test"]).assert_success().stdout_eq(str![[r#" -[COMPILING_FILES] with [SOLC_VERSION] -[SOLC_VERSION] [ELAPSED] -Compiler run successful! - -Ran 1 test for test/Contract.t.sol:FuzzTimeoutTest -[PASS] test_fuzz_bound(uint256) (runs: [..], [AVG_GAS]) -Suite result: ok. 1 passed; 0 failed; 0 skipped; [ELAPSED] - -Ran 1 test suite [ELAPSED]: 1 tests passed, 0 failed, 0 skipped (1 total tests) - -"#]]); -}); - -forgetest_init!(test_fuzz_fail_on_revert, |prj, cmd| { - prj.wipe_contracts(); - prj.update_config(|config| config.fuzz.fail_on_revert = false); - prj.add_source( - "Counter.sol", - r#" -contract Counter { - uint256 public number; - - function setNumber(uint256 newNumber) public { - require(number > 10000000000, "low number"); - number = newNumber; - } -} - "#, - ); - - prj.add_test( - "CounterTest.t.sol", - r#" -import {Test} from "forge-std/Test.sol"; -import "src/Counter.sol"; - -contract CounterTest is Test { - Counter public counter; - - function setUp() public { - counter = new Counter(); - } - - function testFuzz_SetNumberRequire(uint256 x) public { - counter.setNumber(x); - require(counter.number() == 1); - } - - function testFuzz_SetNumberAssert(uint256 x) public { - counter.setNumber(x); - assertEq(counter.number(), 1); - } -} - "#, - ); - - // Tests should not fail as revert happens in Counter contract. - cmd.args(["test", "--mc", "CounterTest"]).assert_success().stdout_eq(str![[r#" -[COMPILING_FILES] with [SOLC_VERSION] -[SOLC_VERSION] [ELAPSED] -Compiler run successful! - -Ran 2 tests for test/CounterTest.t.sol:CounterTest -[PASS] testFuzz_SetNumberAssert(uint256) (runs: 256, [AVG_GAS]) -[PASS] testFuzz_SetNumberRequire(uint256) (runs: 256, [AVG_GAS]) -Suite result: ok. 2 passed; 0 failed; 0 skipped; [ELAPSED] - -Ran 1 test suite [ELAPSED]: 2 tests passed, 0 failed, 0 skipped (2 total tests) - -"#]]); - - // Tested contract does not revert. - prj.add_source( - "Counter.sol", - r#" -contract Counter { - uint256 public number; - - function setNumber(uint256 newNumber) public { - number = newNumber; - } -} - "#, - ); - - // Tests should fail as revert happens in cheatcode (assert) and test (require) contract. - cmd.assert_failure().stdout_eq(str![[r#" -[COMPILING_FILES] with [SOLC_VERSION] -[SOLC_VERSION] [ELAPSED] -Compiler run successful! - -Ran 2 tests for test/CounterTest.t.sol:CounterTest -[FAIL: assertion failed: [..]] testFuzz_SetNumberAssert(uint256) (runs: 0, [AVG_GAS]) -[FAIL: EvmError: Revert; [..]] testFuzz_SetNumberRequire(uint256) (runs: 0, [AVG_GAS]) -Suite result: FAILED. 0 passed; 2 failed; 0 skipped; [ELAPSED] -... - -"#]]); -}); - -// Test 256 runs regardless number of test rejects. -// -forgetest_init!(test_fuzz_runs_with_rejects, |prj, cmd| { - prj.add_test( - "FuzzWithRejectsTest.t.sol", - r#" -import {Test} from "forge-std/Test.sol"; - -contract FuzzWithRejectsTest is Test { - function testFuzzWithRejects(uint256 x) public pure { - vm.assume(x < 1_000_000); - } -} - "#, - ); - - // Tests should not fail as revert happens in Counter contract. - cmd.args(["test", "--mc", "FuzzWithRejectsTest"]).assert_success().stdout_eq(str![[r#" -[COMPILING_FILES] with [SOLC_VERSION] -[SOLC_VERSION] [ELAPSED] -Compiler run successful! - -Ran 1 test for test/FuzzWithRejectsTest.t.sol:FuzzWithRejectsTest -[PASS] testFuzzWithRejects(uint256) (runs: 256, [AVG_GAS]) -Suite result: ok. 1 passed; 0 failed; 0 skipped; [ELAPSED] - -Ran 1 test suite [ELAPSED]: 1 tests passed, 0 failed, 0 skipped (1 total tests) - -"#]]); -}); - -// Test that counterexample is not replayed if test changes. -// -forgetest_init!(test_fuzz_replay_with_changed_test, |prj, cmd| { - prj.update_config(|config| config.fuzz.seed = Some(U256::from(100u32))); - prj.add_test( - "Counter.t.sol", - r#" -import {Test} from "forge-std/Test.sol"; - -contract CounterTest is Test { - function testFuzz_SetNumber(uint256 x) public pure { - require(x > 200); - } -} - "#, - ); - // Tests should fail and record counterexample with value 2. - cmd.args(["test"]).assert_failure().stdout_eq(str![[r#" -... -Failing tests: -Encountered 1 failing test in test/Counter.t.sol:CounterTest -[FAIL: EvmError: Revert; counterexample: calldata=0x5c7f60d70000000000000000000000000000000000000000000000000000000000000002 args=[2]] testFuzz_SetNumber(uint256) (runs: 19, [AVG_GAS]) -... - -"#]]); - - // Change test to assume counterexample 2 is discarded. - prj.add_test( - "Counter.t.sol", - r#" -import {Test} from "forge-std/Test.sol"; - -contract CounterTest is Test { - function testFuzz_SetNumber(uint256 x) public pure { - vm.assume(x != 2); - } -} - "#, - ); - // Test should pass when replay failure with changed assume logic. - cmd.forge_fuse().args(["test"]).assert_success().stdout_eq(str![[r#" -[COMPILING_FILES] with [SOLC_VERSION] -[SOLC_VERSION] [ELAPSED] -Compiler run successful! - -Ran 1 test for test/Counter.t.sol:CounterTest -[PASS] testFuzz_SetNumber(uint256) (runs: 256, [AVG_GAS]) -Suite result: ok. 1 passed; 0 failed; 0 skipped; [ELAPSED] - -Ran 1 test suite [ELAPSED]: 1 tests passed, 0 failed, 0 skipped (1 total tests) - -"#]]); - - // Change test signature. - prj.add_test( - "Counter.t.sol", - r#" -import {Test} from "forge-std/Test.sol"; - -contract CounterTest is Test { - function testFuzz_SetNumber(uint8 x) public pure { - } -} - "#, - ); - // Test should pass when replay failure with changed function signature. - cmd.forge_fuse().args(["test"]).assert_success().stdout_eq(str![[r#" -[COMPILING_FILES] with [SOLC_VERSION] -[SOLC_VERSION] [ELAPSED] -Compiler run successful! - -Ran 1 test for test/Counter.t.sol:CounterTest -[PASS] testFuzz_SetNumber(uint8) (runs: 256, [AVG_GAS]) -Suite result: ok. 1 passed; 0 failed; 0 skipped; [ELAPSED] - -Ran 1 test suite [ELAPSED]: 1 tests passed, 0 failed, 0 skipped (1 total tests) - -"#]]); - - // Change test back to the original one that produced the counterexample. - prj.add_test( - "Counter.t.sol", - r#" -import {Test} from "forge-std/Test.sol"; - -contract CounterTest is Test { - function testFuzz_SetNumber(uint256 x) public pure { - require(x > 200); - } -} - "#, - ); - // Test should fail with replayed counterexample 2 (0 runs). - cmd.forge_fuse().args(["test"]).assert_failure().stdout_eq(str![[r#" -... -Failing tests: -Encountered 1 failing test in test/Counter.t.sol:CounterTest -[FAIL: EvmError: Revert; counterexample: calldata=0x5c7f60d70000000000000000000000000000000000000000000000000000000000000002 args=[2]] testFuzz_SetNumber(uint256) (runs: 0, [AVG_GAS]) -... - -"#]]); -}); diff --git a/crates/forge/tests/it/inline.rs b/crates/forge/tests/it/inline.rs deleted file mode 100644 index 475570a102d67..0000000000000 --- a/crates/forge/tests/it/inline.rs +++ /dev/null @@ -1,70 +0,0 @@ -//! Inline configuration tests. - -use crate::test_helpers::TEST_DATA_DEFAULT; -use forge::result::TestKind; -use foundry_test_utils::Filter; - -#[tokio::test(flavor = "multi_thread")] -async fn inline_config_run_fuzz() { - let filter = Filter::new(".*", ".*", ".*inline/FuzzInlineConf.t.sol"); - let mut runner = TEST_DATA_DEFAULT.runner(); - let result = runner.test_collect(&filter).unwrap(); - let results = result - .into_iter() - .flat_map(|(path, r)| { - r.test_results.into_iter().map(move |(name, t)| { - let runs = match t.kind { - TestKind::Fuzz { runs, .. } => runs, - _ => unreachable!(), - }; - (path.clone(), name, runs) - }) - }) - .collect::>(); - - assert_eq!( - results, - vec![ - ( - "default/inline/FuzzInlineConf.t.sol:FuzzInlineConf".to_string(), - "testInlineConfFuzz(uint8)".to_string(), - 1024 - ), - ( - "default/inline/FuzzInlineConf.t.sol:FuzzInlineConf2".to_string(), - "testInlineConfFuzz1(uint8)".to_string(), - 1 - ), - ( - "default/inline/FuzzInlineConf.t.sol:FuzzInlineConf2".to_string(), - "testInlineConfFuzz2(uint8)".to_string(), - 10 - ), - ] - ); -} - -#[tokio::test(flavor = "multi_thread")] -async fn inline_config_run_invariant() { - const ROOT: &str = "default/inline/InvariantInlineConf.t.sol"; - - let filter = Filter::new(".*", ".*", ".*inline/InvariantInlineConf.t.sol"); - let mut runner = TEST_DATA_DEFAULT.runner(); - let result = runner.test_collect(&filter).unwrap(); - - let suite_result_1 = result.get(&format!("{ROOT}:InvariantInlineConf")).expect("Result exists"); - let suite_result_2 = - result.get(&format!("{ROOT}:InvariantInlineConf2")).expect("Result exists"); - - let test_result_1 = suite_result_1.test_results.get("invariant_neverFalse()").unwrap(); - match test_result_1.kind { - TestKind::Invariant { runs, .. } => assert_eq!(runs, 333), - _ => unreachable!(), - } - - let test_result_2 = suite_result_2.test_results.get("invariant_neverFalse()").unwrap(); - match test_result_2.kind { - TestKind::Invariant { runs, .. } => assert_eq!(runs, 42), - _ => unreachable!(), - } -} diff --git a/crates/forge/tests/it/main.rs b/crates/forge/tests/it/main.rs deleted file mode 100644 index c8890af3d4614..0000000000000 --- a/crates/forge/tests/it/main.rs +++ /dev/null @@ -1,14 +0,0 @@ -pub mod config; -pub mod test_helpers; - -mod cheats; -mod core; -mod fork; -mod fs; -mod fuzz; -mod inline; -mod invariant; -mod repros; -mod spec; -mod table; -mod vyper; diff --git a/crates/forge/tests/it/repros.rs b/crates/forge/tests/it/repros.rs deleted file mode 100644 index e8b1228ad2a5d..0000000000000 --- a/crates/forge/tests/it/repros.rs +++ /dev/null @@ -1,411 +0,0 @@ -//! Regression tests for previous issues. - -use crate::{config::*, test_helpers::TEST_DATA_DEFAULT}; -use alloy_dyn_abi::{DecodedEvent, DynSolValue, EventExt}; -use alloy_json_abi::Event; -use alloy_primitives::{Address, U256, address, b256}; -use forge::{ - decode::decode_console_logs, - result::{TestKind, TestStatus}, -}; -use foundry_config::{Config, FsPermissions, fs_permissions::PathPermission}; -use foundry_evm::{ - constants::HARDHAT_CONSOLE_ADDRESS, - traces::{CallKind, CallTraceDecoder, DecodedCallData, TraceKind}, -}; -use foundry_test_utils::Filter; -use std::sync::Arc; - -/// Creates a test that runs `testdata/repros/Issue{issue}.t.sol`. -macro_rules! test_repro { - ($(#[$attr:meta])* $issue_number:literal $(,)?) => { - test_repro!($(#[$attr])* $issue_number, false, None); - }; - ($(#[$attr:meta])* $issue_number:literal, $should_fail:expr $(,)?) => { - test_repro!($(#[$attr])* $issue_number, $should_fail, None); - }; - ($(#[$attr:meta])* $issue_number:literal, $should_fail:expr, $sender:expr $(,)?) => { - paste::paste! { - #[tokio::test(flavor = "multi_thread")] - $(#[$attr])* - async fn [< issue_ $issue_number >]() { - repro_config($issue_number, $should_fail, $sender.into()).await.run().await; - } - } - }; - ($(#[$attr:meta])* $issue_number:literal, $should_fail:expr, $sender:expr, |$res:ident| $e:expr $(,)?) => { - paste::paste! { - #[tokio::test(flavor = "multi_thread")] - $(#[$attr])* - async fn [< issue_ $issue_number >]() { - let mut $res = repro_config($issue_number, $should_fail, $sender.into()).await.test().unwrap(); - $e - } - } - }; - ($(#[$attr:meta])* $issue_number:literal; |$config:ident| $e:expr $(,)?) => { - paste::paste! { - #[tokio::test(flavor = "multi_thread")] - $(#[$attr])* - async fn [< issue_ $issue_number >]() { - let mut $config = repro_config($issue_number, false, None).await; - $e - $config.run().await; - } - } - }; -} - -async fn repro_config(issue: usize, should_fail: bool, sender: Option
) -> TestConfig { - foundry_test_utils::init_tracing(); - let filter = Filter::path(&format!(".*repros/Issue{issue}.t.sol")); - - let runner = TEST_DATA_DEFAULT.runner_with(|config| { - config.fs_permissions = FsPermissions::new(vec![ - PathPermission::read("./fixtures"), - PathPermission::read("out"), - ]); - if let Some(sender) = sender { - config.sender = sender; - } - }); - TestConfig::with_filter(runner, filter).set_should_fail(should_fail) -} - -// https://github.com/foundry-rs/foundry/issues/2623 -test_repro!(2623); - -// https://github.com/foundry-rs/foundry/issues/2629 -test_repro!(2629); - -// https://github.com/foundry-rs/foundry/issues/2723 -test_repro!(2723); - -// https://github.com/foundry-rs/foundry/issues/2898 -test_repro!(2898); - -// https://github.com/foundry-rs/foundry/issues/2956 -test_repro!(2956); - -// https://github.com/foundry-rs/foundry/issues/2984 -test_repro!(2984); - -// https://github.com/foundry-rs/foundry/issues/3055 -test_repro!(3055, true); - -// https://github.com/foundry-rs/foundry/issues/3077 -test_repro!(3077); - -// https://github.com/foundry-rs/foundry/issues/3110 -test_repro!(3110); - -// https://github.com/foundry-rs/foundry/issues/3119 -test_repro!(3119); - -// https://github.com/foundry-rs/foundry/issues/3189 -test_repro!(3189, true); - -// https://github.com/foundry-rs/foundry/issues/3190 -test_repro!(3190); - -// https://github.com/foundry-rs/foundry/issues/3192 -test_repro!(3192); - -// https://github.com/foundry-rs/foundry/issues/3220 -test_repro!(3220); - -// https://github.com/foundry-rs/foundry/issues/3221 -test_repro!(3221); - -// https://github.com/foundry-rs/foundry/issues/3223 -test_repro!(3223, false, address!("0xF0959944122fb1ed4CfaBA645eA06EED30427BAA")); - -// https://github.com/foundry-rs/foundry/issues/3347 -test_repro!(3347, false, None, |res| { - let mut res = res.remove("default/repros/Issue3347.t.sol:Issue3347Test").unwrap(); - let test = res.test_results.remove("test()").unwrap(); - assert_eq!(test.logs.len(), 1); - let event = Event::parse("event log2(uint256, uint256)").unwrap(); - let decoded = event.decode_log(&test.logs[0].data).unwrap(); - assert_eq!( - decoded, - DecodedEvent { - selector: Some(b256!( - "0x78b9a1f3b55d6797ab2c4537e83ee04ff0c65a1ca1bb39d79a62e0a78d5a8a57" - )), - indexed: vec![], - body: vec![ - DynSolValue::Uint(U256::from(1), 256), - DynSolValue::Uint(U256::from(2), 256) - ] - } - ); -}); - -// https://github.com/foundry-rs/foundry/issues/3596 -test_repro!(3596, true, None); - -// https://github.com/foundry-rs/foundry/issues/3653 -test_repro!(3653); - -// https://github.com/foundry-rs/foundry/issues/3661 -test_repro!(3661); - -// https://github.com/foundry-rs/foundry/issues/3674 -test_repro!(3674, false, address!("0xF0959944122fb1ed4CfaBA645eA06EED30427BAA")); - -// https://github.com/foundry-rs/foundry/issues/3685 -test_repro!(3685); - -// https://github.com/foundry-rs/foundry/issues/3703 -test_repro!( - #[ignore = "flaky polygon RPCs"] - 3703 -); - -// https://github.com/foundry-rs/foundry/issues/3708 -test_repro!(3708); - -// https://github.com/foundry-rs/foundry/issues/3753 -test_repro!(3753); - -// https://github.com/foundry-rs/foundry/issues/3792 -test_repro!(3792); - -// https://github.com/foundry-rs/foundry/issues/4232 -test_repro!(4232); - -// https://github.com/foundry-rs/foundry/issues/4402 -test_repro!(4402); - -// https://github.com/foundry-rs/foundry/issues/4586 -test_repro!(4586); - -// https://github.com/foundry-rs/foundry/issues/4630 -test_repro!(4630); - -// https://github.com/foundry-rs/foundry/issues/4640 -test_repro!(4640); - -// https://github.com/foundry-rs/foundry/issues/5038 -test_repro!(5038); - -// https://github.com/foundry-rs/foundry/issues/5808 -test_repro!(5808); - -// -test_repro!(5929); - -// -test_repro!(5935); - -// -test_repro!(5948); - -// https://github.com/foundry-rs/foundry/issues/6006 -test_repro!(6006); - -// https://github.com/foundry-rs/foundry/issues/6032 -test_repro!(6032); - -// https://github.com/foundry-rs/foundry/issues/6070 -test_repro!(6070); - -// https://github.com/foundry-rs/foundry/issues/6115 -test_repro!(6115); - -// https://github.com/foundry-rs/foundry/issues/6170 -test_repro!(6170, false, None, |res| { - let mut res = res.remove("default/repros/Issue6170.t.sol:Issue6170Test").unwrap(); - let test = res.test_results.remove("test()").unwrap(); - assert_eq!(test.status, TestStatus::Failure); - assert_eq!(test.reason, Some("log != expected log".to_string())); -}); - -// -test_repro!(6293); - -// https://github.com/foundry-rs/foundry/issues/6180 -test_repro!(6180); - -// https://github.com/foundry-rs/foundry/issues/6355 -test_repro!(6355, false, None, |res| { - let mut res = res.remove("default/repros/Issue6355.t.sol:Issue6355Test").unwrap(); - let test = res.test_results.remove("test_shouldFail()").unwrap(); - assert_eq!(test.status, TestStatus::Failure); - - let test = res.test_results.remove("test_shouldFailWithRevertToState()").unwrap(); - assert_eq!(test.status, TestStatus::Failure); -}); - -// https://github.com/foundry-rs/foundry/issues/6437 -test_repro!(6437); - -// Test we decode Hardhat console logs AND traces correctly. -// https://github.com/foundry-rs/foundry/issues/6501 -test_repro!(6501, false, None, |res| { - let mut res = res.remove("default/repros/Issue6501.t.sol:Issue6501Test").unwrap(); - let test = res.test_results.remove("test_hhLogs()").unwrap(); - assert_eq!(test.status, TestStatus::Success); - assert_eq!( - decode_console_logs(&test.logs), - ["a".to_string(), "1".to_string(), "b 2".to_string()] - ); - - let (kind, traces) = test.traces.last().unwrap().clone(); - let nodes = traces.arena.into_nodes(); - assert_eq!(kind, TraceKind::Execution); - - let test_call = nodes.first().unwrap(); - assert_eq!(test_call.idx, 0); - assert_eq!(test_call.children, [1, 2, 3]); - assert_eq!(test_call.trace.depth, 0); - assert!(!test_call.trace.is_error()); - - let expected = [ - ("log(string)", vec!["\"a\""]), - ("log(uint256)", vec!["1"]), - ("log(string,uint256)", vec!["\"b\"", "2"]), - ]; - for (node, expected) in nodes[1..=3].iter().zip(expected) { - let trace = &node.trace; - let decoded = CallTraceDecoder::new().decode_function(trace).await; - assert_eq!(trace.kind, CallKind::StaticCall); - assert_eq!(trace.address, HARDHAT_CONSOLE_ADDRESS); - assert_eq!(decoded.label, Some("console".into())); - assert_eq!(trace.depth, 1); - assert!(!trace.is_error()); - assert_eq!( - decoded.call_data, - Some(DecodedCallData { - signature: expected.0.into(), - args: expected.1.into_iter().map(ToOwned::to_owned).collect(), - }) - ); - } -}); - -// https://github.com/foundry-rs/foundry/issues/6538 -test_repro!(6538); - -// https://github.com/foundry-rs/foundry/issues/6554 -test_repro!(6554; |config| { - let path = config.runner.config.root.join("out/default/Issue6554.t.sol"); - - let mut prj_config = Config::clone(&config.runner.config); - prj_config.fs_permissions.add(PathPermission::read_write(path)); - config.runner.config = Arc::new(prj_config); -}); - -// https://github.com/foundry-rs/foundry/issues/6759 -test_repro!(6759); - -// https://github.com/foundry-rs/foundry/issues/6966 -test_repro!(6966); - -// https://github.com/foundry-rs/foundry/issues/6616 -test_repro!(6616); - -// https://github.com/foundry-rs/foundry/issues/5529 -test_repro!(5529; |config| { - let mut prj_config = Config::clone(&config.runner.config); - prj_config.always_use_create_2_factory = true; - config.runner.evm_opts.always_use_create_2_factory = true; - config.runner.config = Arc::new(prj_config); -}); - -// https://github.com/foundry-rs/foundry/issues/6634 -test_repro!(6634; |config| { - let mut prj_config = Config::clone(&config.runner.config); - prj_config.always_use_create_2_factory = true; - config.runner.evm_opts.always_use_create_2_factory = true; - config.runner.config = Arc::new(prj_config); -}); - -// https://github.com/foundry-rs/foundry/issues/7457 -test_repro!(7457); - -// https://github.com/foundry-rs/foundry/issues/7481 -test_repro!(7481); - -// https://github.com/foundry-rs/foundry/issues/5739 -test_repro!(5739); - -// https://github.com/foundry-rs/foundry/issues/8004 -test_repro!(8004); - -// https://github.com/foundry-rs/foundry/issues/2851 -test_repro!(2851, false, None, |res| { - let mut suite_result = res.remove("default/repros/Issue2851.t.sol:Issue2851Test").unwrap(); - let tr = suite_result.test_results.remove("invariantNotZero()").unwrap(); - assert_eq!(tr.status, TestStatus::Failure, "{tr}"); -}); - -// https://github.com/foundry-rs/foundry/issues/8006 -test_repro!(8006); - -// https://github.com/foundry-rs/foundry/issues/8277 -test_repro!(8277); - -// https://github.com/foundry-rs/foundry/issues/8287 -test_repro!(8287); - -// https://github.com/foundry-rs/foundry/issues/8168 -test_repro!(8168); - -// https://github.com/foundry-rs/foundry/issues/8383 -test_repro!(8383, false, None, |res| { - let mut res = res.remove("default/repros/Issue8383.t.sol:Issue8383Test").unwrap(); - let test = res.test_results.remove("testP256VerifyOutOfBounds()").unwrap(); - assert_eq!(test.status, TestStatus::Success); - match test.kind { - TestKind::Unit { gas } => assert_eq!(gas, 3101), - _ => panic!("not a unit test kind"), - } -}); - -// https://github.com/foundry-rs/foundry/issues/6643 -test_repro!(6643); - -// https://github.com/foundry-rs/foundry/issues/8971 -test_repro!(8971; |config| { - let mut prj_config = Config::clone(&config.runner.config); - prj_config.isolate = true; - config.runner.config = Arc::new(prj_config); -}); - -// https://github.com/foundry-rs/foundry/issues/8639 -test_repro!(8639); - -// https://github.com/foundry-rs/foundry/issues/8566 -test_repro!(8566); - -// https://github.com/foundry-rs/foundry/issues/9643 -test_repro!(9643); - -// https://github.com/foundry-rs/foundry/issues/7238 -test_repro!(7238); - -// https://github.com/foundry-rs/foundry/issues/10302 -test_repro!(10302); - -// https://github.com/foundry-rs/foundry/issues/10477 -test_repro!(10477); - -// https://github.com/foundry-rs/foundry/issues/10527 -test_repro!(10527); - -// https://github.com/foundry-rs/foundry/issues/10552 -test_repro!(10552); - -// https://github.com/foundry-rs/foundry/issues/10586 -test_repro!(10586); - -// https://github.com/foundry-rs/foundry/issues/10957 -test_repro!(10957); - -// https://github.com/foundry-rs/foundry/issues/11353 -test_repro!(11353); - -// https://github.com/foundry-rs/foundry/issues/11616 -test_repro!(11616); diff --git a/crates/forge/tests/it/test_helpers.rs b/crates/forge/tests/it/test_helpers.rs deleted file mode 100644 index 280e6f483abb5..0000000000000 --- a/crates/forge/tests/it/test_helpers.rs +++ /dev/null @@ -1,283 +0,0 @@ -//! Test helpers for Forge integration tests. - -use alloy_chains::NamedChain; -use alloy_primitives::U256; -use forge::{MultiContractRunner, MultiContractRunnerBuilder}; -use foundry_cli::utils::install_crypto_provider; -use foundry_compilers::{ - Project, ProjectCompileOutput, SolcConfig, - artifacts::{EvmVersion, Settings}, - compilers::multi::MultiCompiler, -}; -use foundry_config::{ - Config, FsPermissions, FuzzConfig, FuzzCorpusConfig, FuzzDictionaryConfig, InvariantConfig, - RpcEndpointUrl, RpcEndpoints, fs_permissions::PathPermission, -}; -use foundry_evm::{constants::CALLER, opts::EvmOpts}; -use foundry_test_utils::{ - init_tracing, - rpc::{next_http_archive_rpc_url, next_rpc_endpoint}, - util::get_compiled, -}; -use revm::primitives::hardfork::SpecId; -use std::{ - env, fmt, - path::{Path, PathBuf}, - sync::{Arc, LazyLock}, -}; - -pub const RE_PATH_SEPARATOR: &str = "/"; -const TESTDATA: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/../../testdata"); - -/// Profile for the tests group. Used to configure separate configurations for test runs. -pub enum ForgeTestProfile { - Default, - Paris, - MultiVersion, -} - -impl fmt::Display for ForgeTestProfile { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::Default => write!(f, "default"), - Self::Paris => write!(f, "paris"), - Self::MultiVersion => write!(f, "multi-version"), - } - } -} - -impl ForgeTestProfile { - /// Returns true if the profile is Paris. - pub fn is_paris(&self) -> bool { - matches!(self, Self::Paris) - } - - pub fn root(&self) -> PathBuf { - PathBuf::from(TESTDATA) - } - - /// Configures the solc settings for the test profile. - pub fn solc_config(&self) -> SolcConfig { - let mut settings = Settings::default(); - - if matches!(self, Self::Paris) { - settings.evm_version = Some(EvmVersion::Paris); - } - - let settings = SolcConfig::builder().settings(settings).build(); - SolcConfig { settings } - } - - /// Build [Config] for test profile. - /// - /// Project source files are read from testdata/{profile_name} - /// Project output files are written to testdata/out/{profile_name} - /// Cache is written to testdata/cache/{profile_name} - /// - /// AST output is enabled by default to support inline configs. - pub fn config(&self) -> Config { - let mut config = Config::with_root(self.root()); - - config.ast = true; - config.src = self.root().join(self.to_string()); - config.out = self.root().join("out").join(self.to_string()); - config.cache_path = self.root().join("cache").join(self.to_string()); - - config.prompt_timeout = 0; - - config.optimizer = Some(true); - config.optimizer_runs = Some(200); - - config.gas_limit = u64::MAX.into(); - config.chain = None; - config.tx_origin = CALLER; - config.block_number = U256::from(1); - config.block_timestamp = U256::from(1); - - config.sender = CALLER; - config.initial_balance = U256::MAX; - config.ffi = true; - config.verbosity = 3; - config.memory_limit = 1 << 26; - - if self.is_paris() { - config.evm_version = EvmVersion::Paris; - } - - config.fuzz = FuzzConfig { - runs: 256, - fail_on_revert: true, - max_test_rejects: 65536, - seed: None, - dictionary: FuzzDictionaryConfig { - include_storage: true, - include_push_bytes: true, - dictionary_weight: 40, - max_fuzz_dictionary_addresses: 10_000, - max_fuzz_dictionary_values: 10_000, - }, - gas_report_samples: 256, - corpus: FuzzCorpusConfig::default(), - failure_persist_dir: Some(tempfile::tempdir().unwrap().keep()), - show_logs: false, - timeout: None, - }; - config.invariant = InvariantConfig { - runs: 256, - depth: 15, - fail_on_revert: false, - call_override: false, - dictionary: FuzzDictionaryConfig { - dictionary_weight: 80, - include_storage: true, - include_push_bytes: true, - max_fuzz_dictionary_addresses: 10_000, - max_fuzz_dictionary_values: 10_000, - }, - shrink_run_limit: 5000, - max_assume_rejects: 65536, - gas_report_samples: 256, - corpus: FuzzCorpusConfig::default(), - failure_persist_dir: Some( - tempfile::Builder::new() - .prefix(&format!("foundry-{self}")) - .tempdir() - .unwrap() - .keep(), - ), - show_metrics: true, - timeout: None, - show_solidity: false, - }; - - config.sanitized() - } -} - -/// Container for test data for a specific test profile. -pub struct ForgeTestData { - pub project: Project, - pub output: ProjectCompileOutput, - pub config: Arc, - pub profile: ForgeTestProfile, -} - -impl ForgeTestData { - /// Builds [ForgeTestData] for the given [ForgeTestProfile]. - /// - /// Uses [get_compiled] to lazily compile the project. - pub fn new(profile: ForgeTestProfile) -> Self { - install_crypto_provider(); - init_tracing(); - let config = Arc::new(profile.config()); - let mut project = config.project().unwrap(); - let output = get_compiled(&mut project); - Self { project, output, config, profile } - } - - /// Builds a base runner - pub fn base_runner(&self) -> MultiContractRunnerBuilder { - init_tracing(); - let config = self.config.clone(); - let mut runner = MultiContractRunnerBuilder::new(config).sender(self.config.sender); - if self.profile.is_paris() { - runner = runner.evm_spec(SpecId::MERGE); - } - runner - } - - /// Builds a non-tracing runner - pub fn runner(&self) -> MultiContractRunner { - self.runner_with(|_| {}) - } - - /// Builds a non-tracing runner - pub fn runner_with(&self, modify: impl FnOnce(&mut Config)) -> MultiContractRunner { - let mut config = (*self.config).clone(); - modify(&mut config); - self.runner_with_config(config) - } - - fn runner_with_config(&self, mut config: Config) -> MultiContractRunner { - config.rpc_endpoints = rpc_endpoints(); - config.allow_paths.push(manifest_root().to_path_buf()); - - if config.fs_permissions.is_empty() { - config.fs_permissions = - FsPermissions::new(vec![PathPermission::read_write(manifest_root())]); - } - - let opts = config_evm_opts(&config); - - let mut builder = self.base_runner(); - let config = Arc::new(config); - builder.config = config.clone(); - builder - .enable_isolation(opts.isolate) - .sender(config.sender) - .build::(&self.output, opts.local_evm_env(), opts) - .unwrap() - } - - /// Builds a tracing runner - pub fn tracing_runner(&self) -> MultiContractRunner { - let mut opts = config_evm_opts(&self.config); - opts.verbosity = 5; - self.base_runner().build::(&self.output, opts.local_evm_env(), opts).unwrap() - } - - /// Builds a runner that runs against forked state - pub async fn forked_runner(&self, rpc: &str) -> MultiContractRunner { - let mut opts = config_evm_opts(&self.config); - - opts.env.chain_id = None; // clear chain id so the correct one gets fetched from the RPC - opts.fork_url = Some(rpc.to_string()); - - let env = opts.evm_env().await.expect("Could not instantiate fork environment"); - let fork = opts.get_fork(&Default::default(), env.clone()); - - self.base_runner().with_fork(fork).build::(&self.output, env, opts).unwrap() - } -} - -/// Default data for the tests group. -pub static TEST_DATA_DEFAULT: LazyLock = - LazyLock::new(|| ForgeTestData::new(ForgeTestProfile::Default)); - -/// 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 no specific version on Solc and EVM level. -pub static TEST_DATA_MULTI_VERSION: LazyLock = - LazyLock::new(|| ForgeTestData::new(ForgeTestProfile::MultiVersion)); - -pub fn manifest_root() -> &'static Path { - let mut root = Path::new(env!("CARGO_MANIFEST_DIR")); - // need to check here where we're executing the test from, if in `forge` we need to also allow - // `testdata` - if root.ends_with("forge") { - root = root.parent().unwrap(); - } - root -} - -/// the RPC endpoints used during tests -pub fn rpc_endpoints() -> RpcEndpoints { - RpcEndpoints::new([ - ("mainnet", RpcEndpointUrl::Url(next_http_archive_rpc_url())), - ("mainnet2", RpcEndpointUrl::Url(next_http_archive_rpc_url())), - ("sepolia", RpcEndpointUrl::Url(next_rpc_endpoint(NamedChain::Sepolia))), - ("optimism", RpcEndpointUrl::Url(next_rpc_endpoint(NamedChain::Optimism))), - ("arbitrum", RpcEndpointUrl::Url(next_rpc_endpoint(NamedChain::Arbitrum))), - ("polygon", RpcEndpointUrl::Url(next_rpc_endpoint(NamedChain::Polygon))), - ("bsc", RpcEndpointUrl::Url(next_rpc_endpoint(NamedChain::BinanceSmartChain))), - ("avaxTestnet", RpcEndpointUrl::Url("https://api.avax-test.network/ext/bc/C/rpc".into())), - ("moonbeam", RpcEndpointUrl::Url("https://moonbeam-rpc.publicnode.com".into())), - ("rpcEnvAlias", RpcEndpointUrl::Env("${RPC_ENV_ALIAS}".into())), - ]) -} - -fn config_evm_opts(config: &Config) -> EvmOpts { - config.to_figment(foundry_config::FigmentProviders::None).extract().unwrap() -} diff --git a/crates/forge/tests/it/vyper.rs b/crates/forge/tests/it/vyper.rs deleted file mode 100644 index c40b87541bfb9..0000000000000 --- a/crates/forge/tests/it/vyper.rs +++ /dev/null @@ -1,10 +0,0 @@ -//! Integration tests for EVM specifications. - -use crate::{config::*, test_helpers::TEST_DATA_DEFAULT}; -use foundry_test_utils::Filter; - -#[tokio::test(flavor = "multi_thread")] -async fn test_basic_vyper_test() { - let filter = Filter::new("", "CounterTest", ".*vyper"); - TestConfig::with_filter(TEST_DATA_DEFAULT.runner(), filter).run().await; -} diff --git a/crates/linking/src/lib.rs b/crates/linking/src/lib.rs index 43acb20cd24bf..33fad7418ac2f 100644 --- a/crates/linking/src/lib.rs +++ b/crates/linking/src/lib.rs @@ -409,9 +409,8 @@ mod tests { .to_string_lossy(); let identifier = format!("{source}:{}", id.name); - // Skip ds-test as it always has no dependencies etc. (and the path is outside root - // so is not sanitized) - if identifier.contains("DSTest") { + // Skip test utils as they always have no dependencies. + if identifier.contains("utils/") { return None; } @@ -701,7 +700,7 @@ mod tests { "default/linking/nested/Nested.t.sol:NestedLib", &[( "default/linking/nested/Nested.t.sol:Lib", - address!("0xddb1Cd2497000DAeA687CEa3dc34Af44084BEa74"), + address!("0x773253227cce756e50c3993ec6366b3ec27786f9"), )], ) .assert_dependencies( @@ -711,12 +710,12 @@ mod tests { // have the same address and nonce. ( "default/linking/nested/Nested.t.sol:Lib", - Address::from_str("0xddb1Cd2497000DAeA687CEa3dc34Af44084BEa74") + Address::from_str("0x773253227cce756e50c3993ec6366b3ec27786f9") .unwrap(), ), ( "default/linking/nested/Nested.t.sol:NestedLib", - Address::from_str("0xfebE2F30641170642f317Ff6F644Cee60E7Ac369") + Address::from_str("0xac231df03403867b05d092c26fc91b6b83f4bebe") .unwrap(), ), ], @@ -726,12 +725,12 @@ mod tests { &[ ( "default/linking/nested/Nested.t.sol:Lib", - Address::from_str("0xddb1Cd2497000DAeA687CEa3dc34Af44084BEa74") + Address::from_str("0x773253227cce756e50c3993ec6366b3ec27786f9") .unwrap(), ), ( "default/linking/nested/Nested.t.sol:NestedLib", - Address::from_str("0xfebE2F30641170642f317Ff6F644Cee60E7Ac369") + Address::from_str("0xac231df03403867b05d092c26fc91b6b83f4bebe") .unwrap(), ), ], diff --git a/crates/test-utils/src/rpc.rs b/crates/test-utils/src/rpc.rs index cf0844429b0ee..52b5446ebdb73 100644 --- a/crates/test-utils/src/rpc.rs +++ b/crates/test-utils/src/rpc.rs @@ -1,10 +1,10 @@ //! RPC API keys utilities. use foundry_config::{ - NamedChain, NamedChain::{ - Arbitrum, Base, BinanceSmartChainTestnet, Celo, Mainnet, Optimism, Polygon, Sepolia, + self, Arbitrum, Base, BinanceSmartChainTestnet, Celo, Mainnet, Optimism, Polygon, Sepolia, }, + RpcEndpointUrl, RpcEndpoints, }; use rand::seq::SliceRandom; use std::sync::{ @@ -90,6 +90,22 @@ fn next(list: &[T]) -> &T { &list[next_idx() % list.len()] } +/// the RPC endpoints used during tests +pub fn rpc_endpoints() -> RpcEndpoints { + RpcEndpoints::new([ + ("mainnet", RpcEndpointUrl::Url(next_http_archive_rpc_url())), + ("mainnet2", RpcEndpointUrl::Url(next_http_archive_rpc_url())), + ("sepolia", RpcEndpointUrl::Url(next_rpc_endpoint(NamedChain::Sepolia))), + ("optimism", RpcEndpointUrl::Url(next_rpc_endpoint(NamedChain::Optimism))), + ("arbitrum", RpcEndpointUrl::Url(next_rpc_endpoint(NamedChain::Arbitrum))), + ("polygon", RpcEndpointUrl::Url(next_rpc_endpoint(NamedChain::Polygon))), + ("bsc", RpcEndpointUrl::Url(next_rpc_endpoint(NamedChain::BinanceSmartChain))), + ("avaxTestnet", RpcEndpointUrl::Url("https://api.avax-test.network/ext/bc/C/rpc".into())), + ("moonbeam", RpcEndpointUrl::Url("https://moonbeam-rpc.publicnode.com".into())), + ("rpcEnvAlias", RpcEndpointUrl::Env("${RPC_ENV_ALIAS}".into())), + ]) +} + /// Returns the next _mainnet_ rpc URL in inline /// /// This will rotate all available rpc endpoints diff --git a/crates/test-utils/src/script.rs b/crates/test-utils/src/script.rs index 2dfd11986d13c..839a3bfe8b224 100644 --- a/crates/test-utils/src/script.rs +++ b/crates/test-utils/src/script.rs @@ -21,17 +21,7 @@ fn init_script_cmd( cmd.forge_fuse(); cmd.set_current_dir(project_root); - cmd.args([ - "script", - "-R", - "ds-test/=lib/", - "-R", - "cheats/=cheats/", - target_contract, - "--root", - project_root.to_str().unwrap(), - "-vvvvv", - ]); + cmd.args(["script", target_contract, "--root", project_root.to_str().unwrap(), "-vvvvv"]); if let Some(rpc_url) = endpoint { cmd.args(["--fork-url", rpc_url]); @@ -125,11 +115,16 @@ impl ScriptTester { } /// Initialises the test contracts by copying them into the workspace - fn copy_testdata(current_dir: &Path) -> Result<()> { + fn copy_testdata(root: &Path) -> Result<()> { let testdata = Self::testdata_path(); - fs::create_dir_all(current_dir.join("cheats"))?; - fs::copy(testdata.join("cheats/Vm.sol"), current_dir.join("cheats/Vm.sol"))?; - fs::copy(testdata.join("lib/ds-test/src/test.sol"), current_dir.join("lib/test.sol"))?; + let from_dir = testdata.join("utils"); + let to_dir = root.join("utils"); + fs::create_dir_all(&to_dir)?; + for entry in fs::read_dir(&from_dir)? { + let file = &entry?.path(); + let name = file.file_name().unwrap(); + fs::copy(file, to_dir.join(name))?; + } Ok(()) } diff --git a/crates/test-utils/src/util.rs b/crates/test-utils/src/util.rs index a8d33e615fede..1f58821a574a6 100644 --- a/crates/test-utils/src/util.rs +++ b/crates/test-utils/src/util.rs @@ -1,4 +1,4 @@ -use crate::init_tracing; +use crate::{init_tracing, rpc::rpc_endpoints}; use eyre::{Result, WrapErr}; use foundry_compilers::{ ArtifactOutput, ConfigurableArtifacts, PathStyle, Project, ProjectCompileOutput, @@ -642,6 +642,13 @@ impl TestProject { pretty_err(&file, fs::write(&file, config.to_string_pretty().unwrap())); } + /// Writes [`rpc_endpoints`] to the project's config. + pub fn add_rpc_endpoints(&self) { + self.update_config(|config| { + config.rpc_endpoints = rpc_endpoints(); + }); + } + /// Adds a source file to the project. pub fn add_source(&self, name: &str, contents: &str) -> PathBuf { self.inner.add_source(name, Self::add_source_prelude(contents)).unwrap() @@ -740,19 +747,26 @@ impl TestProject { /// Adds DSTest as a source under "test.sol" pub fn insert_ds_test(&self) -> PathBuf { - let s = include_str!("../../../testdata/lib/ds-test/src/test.sol"); - self.add_source("test.sol", s) + self.add_source("test.sol", include_str!("../../../testdata/utils/DSTest.sol")) + } + + /// Adds custom test utils under the "test/utils" directory. + pub fn insert_utils(&self) { + self.add_test("utils/DSTest.sol", include_str!("../../../testdata/utils/DSTest.sol")); + self.add_test("utils/Test.sol", include_str!("../../../testdata/utils/Test.sol")); + self.add_test("utils/Vm.sol", include_str!("../../../testdata/utils/Vm.sol")); + self.add_test("utils/console.sol", include_str!("../../../testdata/utils/console.sol")); } /// Adds `console.sol` as a source under "console.sol" pub fn insert_console(&self) -> PathBuf { - let s = include_str!("../../../testdata/default/logs/console.sol"); + let s = include_str!("../../../testdata/utils/console.sol"); self.add_source("console.sol", s) } /// Adds `Vm.sol` as a source under "Vm.sol" pub fn insert_vm(&self) -> PathBuf { - let s = include_str!("../../../testdata/cheats/Vm.sol"); + let s = include_str!("../../../testdata/utils/Vm.sol"); self.add_source("Vm.sol", s) } @@ -1039,14 +1053,26 @@ impl TestCommand { /// Runs the command, returning a [`snapbox`] object to assert the command output. #[track_caller] - pub fn assert(&mut self) -> OutputAssert { + pub fn assert_with(&mut self, f: &[RegexRedaction]) -> OutputAssert { let assert = OutputAssert::new(self.execute()); if self.redact_output { - return assert.with_assert(test_assert()); + let mut redactions = test_redactions(); + insert_redactions(f, &mut redactions); + return assert.with_assert( + snapbox::Assert::new() + .action_env(snapbox::assert::DEFAULT_ACTION_ENV) + .redact_with(redactions), + ); } assert } + /// Runs the command, returning a [`snapbox`] object to assert the command output. + #[track_caller] + pub fn assert(&mut self) -> OutputAssert { + self.assert_with(&[]) + } + /// Runs the command and asserts that it resulted in success. #[track_caller] pub fn assert_success(&mut self) -> OutputAssert { @@ -1142,16 +1168,9 @@ impl TestCommand { } } -fn test_assert() -> snapbox::Assert { - snapbox::Assert::new() - .action_env(snapbox::assert::DEFAULT_ACTION_ENV) - .redact_with(test_redactions()) -} - fn test_redactions() -> snapbox::Redactions { static REDACTIONS: LazyLock = LazyLock::new(|| { - let mut r = snapbox::Redactions::new(); - let redactions = [ + make_redactions(&[ ("[SOLC_VERSION]", r"Solc( version)? \d+.\d+.\d+"), ("[ELAPSED]", r"(finished )?in \d+(\.\d+)?\w?s( \(.*?s CPU time\))?"), ("[GAS]", r"[Gg]as( used)?: \d+"), @@ -1174,15 +1193,27 @@ fn test_redactions() -> snapbox::Redactions { "[ESTIMATED_AMOUNT_REQUIRED]", r"Estimated amount required:\s*(\d+(\.\d+)?)\s*[A-Z]{3}", ), - ]; - for (placeholder, re) in redactions { - r.insert(placeholder, Regex::new(re).expect(re)).expect(re); - } - r + ]) }); REDACTIONS.clone() } +/// A tuple of a placeholder and a regex replacement string. +type RegexRedaction = (&'static str, &'static str); + +/// Creates a [`snapbox`] redactions object from a list of regex redactions. +fn make_redactions(redactions: &[RegexRedaction]) -> snapbox::Redactions { + let mut r = snapbox::Redactions::new(); + insert_redactions(redactions, &mut r); + r +} + +fn insert_redactions(redactions: &[RegexRedaction], r: &mut snapbox::Redactions) { + for &(placeholder, re) in redactions { + r.insert(placeholder, Regex::new(re).expect(re)).expect(re); + } +} + /// Extension trait for [`Output`]. pub trait OutputExt { /// Returns the stdout as lossy string diff --git a/testdata/default/cheats/AccessList.t.sol b/testdata/default/cheats/AccessList.t.sol index 4615ab588adba..f59e8cdb439c3 100644 --- a/testdata/default/cheats/AccessList.t.sol +++ b/testdata/default/cheats/AccessList.t.sol @@ -1,12 +1,10 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract AccessListIsolatedTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +/// forge-config: default.isolate = true +contract AccessListIsolatedTest is Test { function test_access_list() public { Write anotherWrite = new Write(); Write write = new Write(); diff --git a/testdata/default/cheats/Addr.t.sol b/testdata/default/cheats/Addr.t.sol index b0b3fefbdba79..82b8cf7d277f0 100644 --- a/testdata/default/cheats/Addr.t.sol +++ b/testdata/default/cheats/Addr.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract AddrTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract AddrTest is Test { /// forge-config: default.allow_internal_expect_revert = true function testRevertIfPkZero() public { vm.expectRevert("vm.addr: private key cannot be 0"); diff --git a/testdata/default/cheats/ArbitraryStorage.t.sol b/testdata/default/cheats/ArbitraryStorage.t.sol index 1b5585b681b3d..407d14448a996 100644 --- a/testdata/default/cheats/ArbitraryStorage.t.sol +++ b/testdata/default/cheats/ArbitraryStorage.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract Counter { uint256 public a; @@ -27,9 +26,8 @@ contract Counter { } } -contract CounterArbitraryStorageWithSeedTest is DSTest { - Vm vm = Vm(HEVM_ADDRESS); - +/// forge-config: default.fuzz.seed = "100" +contract CounterArbitraryStorageWithSeedTest is Test { function test_fresh_storage() public { uint256 index = 55; Counter counter = new Counter(); @@ -77,9 +75,8 @@ contract AContract { bytes32[] public d; } -contract AContractArbitraryStorageWithSeedTest is DSTest { - Vm vm = Vm(HEVM_ADDRESS); - +/// forge-config: default.fuzz.seed = "100" +contract AContractArbitraryStorageWithSeedTest is Test { function test_arbitrary_storage_with_seed() public { AContract target = new AContract(); vm.setArbitraryStorage(address(target)); @@ -96,9 +93,8 @@ contract SymbolicStore { constructor() {} } -contract SymbolicStorageWithSeedTest is DSTest { - Vm vm = Vm(HEVM_ADDRESS); - +/// forge-config: default.fuzz.seed = "100" +contract SymbolicStorageWithSeedTest is Test { function test_SymbolicStorage() public { uint256 slot = vm.randomUint(0, 100); address addr = 0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8; @@ -125,8 +121,8 @@ contract SymbolicStorageWithSeedTest is DSTest { } // -contract ArbitraryStorageOverwriteWithSeedTest is DSTest { - Vm vm = Vm(HEVM_ADDRESS); +/// forge-config: default.fuzz.seed = "100" +contract ArbitraryStorageOverwriteWithSeedTest is Test { uint256 _value; function testArbitraryStorageFalse(uint256 value) public { diff --git a/testdata/default/cheats/Assert.t.sol b/testdata/default/cheats/Assert.t.sol index ea093efc4fcb2..d29a7dba3e604 100644 --- a/testdata/default/cheats/Assert.t.sol +++ b/testdata/default/cheats/Assert.t.sol @@ -1,15 +1,12 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; -contract AssertionsTest is DSTest { +contract AssertionsTest is Test { string constant errorMessage = "User provided message"; uint256 constant maxDecimals = 77; - Vm constant vm = Vm(HEVM_ADDRESS); - function _abs(int256 a) internal pure returns (uint256) { // Required or it will fail when `a = type(int256).min` if (a == type(int256).min) { diff --git a/testdata/default/cheats/Assume.t.sol b/testdata/default/cheats/Assume.t.sol index 14ed341c9970e..91de77f246e3b 100644 --- a/testdata/default/cheats/Assume.t.sol +++ b/testdata/default/cheats/Assume.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract AssumeTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract AssumeTest is Test { function testAssume(uint8 x) public { vm.assume(x < 2 ** 7); assertTrue(x < 2 ** 7, "did not discard inputs"); diff --git a/testdata/default/cheats/AssumeNoRevert.t.sol b/testdata/default/cheats/AssumeNoRevert.t.sol index ea6d2d9747bdd..f6a017efec212 100644 --- a/testdata/default/cheats/AssumeNoRevert.t.sol +++ b/testdata/default/cheats/AssumeNoRevert.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import {DSTest as Test} from "ds-test/test.sol"; -import {Vm} from "cheats/Vm.sol"; +import "utils/Test.sol"; contract ReverterB { /// @notice has same error selectors as contract below to test the `reverter` param @@ -62,7 +61,6 @@ contract Reverter { contract ReverterTest is Test { Reverter reverter; - Vm _vm = Vm(HEVM_ADDRESS); function setUp() public { reverter = new Reverter(); @@ -70,7 +68,7 @@ contract ReverterTest is Test { /// @dev Test that `assumeNoRevert` anticipates and correctly rejects a specific error selector function testAssumeSelector(uint256 x) public view { - _vm.assumeNoRevert( + vm.assumeNoRevert( Vm.PotentialRevert({ revertData: abi.encodeWithSelector(Reverter.MyRevert.selector), partialMatch: false, @@ -82,7 +80,7 @@ contract ReverterTest is Test { /// @dev Test that `assumeNoRevert` anticipates and correctly rejects a specific error selector and data function testAssumeWithDataSingle(uint256 x) public view { - _vm.assumeNoRevert( + vm.assumeNoRevert( Vm.PotentialRevert({ revertData: abi.encodeWithSelector(Reverter.RevertWithData.selector, 2), partialMatch: false, @@ -94,7 +92,7 @@ contract ReverterTest is Test { /// @dev Test that `assumeNoRevert` anticipates and correctly rejects a specific error selector with any extra data (ie providing selector allows for arbitrary extra data) function testAssumeWithDataPartial(uint256 x) public view { - _vm.assumeNoRevert( + vm.assumeNoRevert( Vm.PotentialRevert({ revertData: abi.encodeWithSelector(Reverter.RevertWithData.selector), partialMatch: true, @@ -106,14 +104,14 @@ contract ReverterTest is Test { /// @dev Test that `assumeNoRevert` assumptions are not cleared after a cheatcode call function testAssumeNotClearedAfterCheatcodeCall(uint256 x) public { - _vm.assumeNoRevert( + vm.assumeNoRevert( Vm.PotentialRevert({ revertData: abi.encodeWithSelector(Reverter.MyRevert.selector), partialMatch: false, reverter: address(0) }) ); - _vm.warp(block.timestamp + 1000); + vm.warp(block.timestamp + 1000); reverter.revertIf2(x); } @@ -130,7 +128,7 @@ contract ReverterTest is Test { partialMatch: false, reverter: address(reverter) }); - _vm.assumeNoRevert(revertData); + vm.assumeNoRevert(revertData); reverter.twoPossibleReverts(x); } @@ -147,7 +145,7 @@ contract ReverterTest is Test { partialMatch: false, reverter: address(reverter) }); - _vm.assumeNoRevert(revertData); + vm.assumeNoRevert(revertData); reverter.twoPossibleReverts(x); } } diff --git a/testdata/default/cheats/AttachBlob.t.sol b/testdata/default/cheats/AttachBlob.t.sol index db17c1fae5f4c..1be49ceef2e5c 100644 --- a/testdata/default/cheats/AttachBlob.t.sol +++ b/testdata/default/cheats/AttachBlob.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.25; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract Counter { uint256 public counter; @@ -12,8 +11,7 @@ contract Counter { } } -contract AttachBlobTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +contract AttachBlobTest is Test { uint256 bobPk = 0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d; address bob = 0x70997970C51812dc3A010C7d01b50e0d17dc79C8; diff --git a/testdata/default/cheats/AttachDelegation.t.sol b/testdata/default/cheats/AttachDelegation.t.sol index a4e870d4cee9e..63e00462d85ba 100644 --- a/testdata/default/cheats/AttachDelegation.t.sol +++ b/testdata/default/cheats/AttachDelegation.t.sol @@ -1,13 +1,11 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity 0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; -contract AttachDelegationTest is DSTest { +contract AttachDelegationTest is Test { event ExecutedBy(uint256 id); - Vm constant vm = Vm(HEVM_ADDRESS); uint256 alice_pk = 0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d; address payable alice = payable(0x70997970C51812dc3A010C7d01b50e0d17dc79C8); uint256 bob_pk = 0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a; diff --git a/testdata/default/cheats/Bank.t.sol b/testdata/default/cheats/Bank.t.sol index 166fbb16ac8ea..bcda62aa6d676 100644 --- a/testdata/default/cheats/Bank.t.sol +++ b/testdata/default/cheats/Bank.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract CoinbaseTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract CoinbaseTest is Test { function testCoinbase() public { vm.coinbase(0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8); assertEq(block.coinbase, 0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8, "coinbase failed"); diff --git a/testdata/default/cheats/Base64.t.sol b/testdata/default/cheats/Base64.t.sol index fad7bbf4f297c..c96ca6b4b3a79 100644 --- a/testdata/default/cheats/Base64.t.sol +++ b/testdata/default/cheats/Base64.t.sol @@ -1,13 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; -import "../logs/console.sol"; - -contract Base64Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract Base64Test is Test { function test_toBase64() public { bytes memory input = hex"00112233445566778899aabbccddeeff"; string memory expected = "ABEiM0RVZneImaq7zN3u/w=="; diff --git a/testdata/default/cheats/BlobBaseFee.t.sol b/testdata/default/cheats/BlobBaseFee.t.sol index 54fbc8f7f0616..6ce979d046eda 100644 --- a/testdata/default/cheats/BlobBaseFee.t.sol +++ b/testdata/default/cheats/BlobBaseFee.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.25; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract BlobBaseFeeTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract BlobBaseFeeTest is Test { function test_blob_base_fee() public { vm.blobBaseFee(6969); assertEq(vm.getBlobBaseFee(), 6969); diff --git a/testdata/default/cheats/Blobhashes.t.sol b/testdata/default/cheats/Blobhashes.t.sol index 4a589b45a38ff..6cf672c540d29 100644 --- a/testdata/default/cheats/Blobhashes.t.sol +++ b/testdata/default/cheats/Blobhashes.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.25; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract BlobhashesTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract BlobhashesTest is Test { function testSetAndGetBlobhashes() public { bytes32[] memory blobhashes = new bytes32[](2); blobhashes[0] = bytes32(0x0000000000000000000000000000000000000000000000000000000000000001); diff --git a/testdata/default/cheats/Broadcast.t.sol b/testdata/default/cheats/Broadcast.t.sol index 9916ca0efc799..3912ea1756d82 100644 --- a/testdata/default/cheats/Broadcast.t.sol +++ b/testdata/default/cheats/Broadcast.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import {Test as ForgeTest} from "utils/Test.sol"; library F { function t2() public pure returns (uint256) { @@ -10,7 +9,7 @@ library F { } } -contract Test is DSTest { +contract Test is ForgeTest { uint256 public changed = 0; function t(uint256 a) public returns (uint256) { @@ -33,9 +32,7 @@ contract Test is DSTest { } } -contract BroadcastTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract BroadcastTest is ForgeTest { // 1st anvil account address public ACCOUNT_A = 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266; // 2nd anvil account @@ -160,7 +157,7 @@ contract BroadcastTest is DSTest { // } } -contract NoLink is DSTest { +contract NoLink is ForgeTest { function t(uint256 a) public returns (uint256) { uint256 b = 0; for (uint256 i; i < a; i++) { @@ -179,9 +176,7 @@ interface INoLink { function t(uint256 a) external returns (uint256); } -contract BroadcastTestNoLinking is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract BroadcastTestNoLinking is ForgeTest { // ganache-cli -d 1st address public ACCOUNT_A = 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266; @@ -254,9 +249,7 @@ contract BroadcastTestNoLinking is DSTest { } } -contract BroadcastMix is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract BroadcastMix is ForgeTest { // ganache-cli -d 1st address public ACCOUNT_A = 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266; @@ -312,9 +305,7 @@ contract BroadcastMix is DSTest { } } -contract BroadcastTestSetup is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract BroadcastTestSetup is ForgeTest { function setUp() public { // It predeployed a library first assert(vm.getNonce(msg.sender) == 1); @@ -338,9 +329,7 @@ contract BroadcastTestSetup is DSTest { } } -contract BroadcastTestLog is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract BroadcastTestLog is ForgeTest { function run() public { uint256[] memory arr = new uint256[](2); arr[0] = 3; @@ -361,14 +350,12 @@ contract BroadcastTestLog is DSTest { } } -contract TestInitialBalance is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract TestInitialBalance is ForgeTest { function runCustomSender() public { // Make sure we're testing a different caller than the default one. assert(msg.sender != address(0x00a329c0648769A73afAc7F9381E08FB43dBEA72)); - // NodeConfig::test() sets the balance of the address used in this test to 100 ether. + // NodeConfig::test() sets the balance of the address used in this ForgeTest to 100 ether. assert(msg.sender.balance == 100 ether); vm.broadcast(); @@ -386,9 +373,7 @@ contract TestInitialBalance is DSTest { } } -contract MultiChainBroadcastNoLink is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract MultiChainBroadcastNoLink is ForgeTest { // ganache-cli -d 1st address public ACCOUNT_A = 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266; @@ -431,9 +416,7 @@ contract MultiChainBroadcastNoLink is DSTest { } } -contract MultiChainBroadcastLink is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract MultiChainBroadcastLink is ForgeTest { // ganache-cli -d 1st address public ACCOUNT_A = 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266; @@ -454,9 +437,7 @@ contract MultiChainBroadcastLink is DSTest { } } -contract BroadcastEmptySetUp is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract BroadcastEmptySetUp is ForgeTest { function setUp() public {} function run() public { @@ -495,9 +476,7 @@ contract ContractB { } } -contract CheckOverrides is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract CheckOverrides is ForgeTest { function run() external { // `script_caller` can be set by `--private-key ...` or `--sender ...` // Otherwise it will take the default value of 0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38 @@ -546,9 +525,7 @@ contract Parent { } } -contract ScriptAdditionalContracts is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract ScriptAdditionalContracts is ForgeTest { function run() external { vm.startBroadcast(); new Parent(); @@ -567,8 +544,7 @@ contract SignatureTester { } } -contract ScriptSign is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +contract ScriptSign is ForgeTest { bytes32 digest = keccak256("something"); function run() external { diff --git a/testdata/default/cheats/BroadcastRawTransaction.t.sol b/testdata/default/cheats/BroadcastRawTransaction.t.sol index 3806580281f73..9cf6c4950e37a 100644 --- a/testdata/default/cheats/BroadcastRawTransaction.t.sol +++ b/testdata/default/cheats/BroadcastRawTransaction.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract BroadcastRawTransactionTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract BroadcastRawTransactionTest is Test { function test_revert_not_a_tx() public { vm._expectCheatcodeRevert("failed to decode RLP-encoded transaction: unexpected string"); vm.broadcastRawTransaction(hex"0102"); @@ -277,9 +274,7 @@ contract MyERC20 { } } -contract ScriptBroadcastRawTransactionBroadcast is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract ScriptBroadcastRawTransactionBroadcast is Test { function runSignedTxBroadcast() public { uint256 pk_to = 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80; vm.startBroadcast(pk_to); diff --git a/testdata/default/cheats/ChainId.t.sol b/testdata/default/cheats/ChainId.t.sol index ef0108e7e208e..bc2c69b798942 100644 --- a/testdata/default/cheats/ChainId.t.sol +++ b/testdata/default/cheats/ChainId.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract ChainIdTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract ChainIdTest is Test { function testChainId() public { uint256 newChainId = 99; vm.chainId(newChainId); diff --git a/testdata/default/cheats/CloneAccount.t.sol b/testdata/default/cheats/CloneAccount.t.sol index d584c747cb9b9..95eccd843ee09 100644 --- a/testdata/default/cheats/CloneAccount.t.sol +++ b/testdata/default/cheats/CloneAccount.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract Source { uint256 public a; @@ -20,9 +19,7 @@ contract Source { } } -contract CloneAccountTest is DSTest { - Vm vm = Vm(HEVM_ADDRESS); - +contract CloneAccountTest is Test { address clone = address(777); function setUp() public { diff --git a/testdata/default/cheats/Cool.t.sol b/testdata/default/cheats/Cool.t.sol index d0750bebfa18e..71e19e4f8fd88 100644 --- a/testdata/default/cheats/Cool.t.sol +++ b/testdata/default/cheats/Cool.t.sol @@ -1,11 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "lib/ds-test/src/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; -contract CoolTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +contract CoolTest is Test { uint256 public slot0 = 1; function testCool_SLOAD_normal() public { diff --git a/testdata/default/cheats/CopyStorage.t.sol b/testdata/default/cheats/CopyStorage.t.sol index e9195949e49c9..881a0c0aacf57 100644 --- a/testdata/default/cheats/CopyStorage.t.sol +++ b/testdata/default/cheats/CopyStorage.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract Counter { uint256 public a; @@ -18,10 +17,10 @@ contract Counter { } } -contract CounterWithSeedTest is DSTest { +/// forge-config: default.fuzz.seed = "100" +contract CounterWithSeedTest is Test { Counter public counter; Counter public counter1; - Vm vm = Vm(HEVM_ADDRESS); function test_copy_storage() public { counter = new Counter(); @@ -67,11 +66,10 @@ contract CopyStorageContract { uint256 public x; } -contract CopyStorageTest is DSTest { +contract CopyStorageTest is Test { CopyStorageContract csc_1; CopyStorageContract csc_2; CopyStorageContract csc_3; - Vm vm = Vm(HEVM_ADDRESS); function _storeUInt256(address contractAddress, uint256 slot, uint256 value) internal { vm.store(contractAddress, bytes32(slot), bytes32(value)); diff --git a/testdata/default/cheats/Deal.t.sol b/testdata/default/cheats/Deal.t.sol index a46d9e7140e3e..4fcb37249aa67 100644 --- a/testdata/default/cheats/Deal.t.sol +++ b/testdata/default/cheats/Deal.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract DealTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract DealTest is Test { function testDeal(uint256 amount) public { address target = address(10); assertEq(target.balance, 0, "initial balance incorrect"); diff --git a/testdata/default/cheats/DeployCode.t.sol b/testdata/default/cheats/DeployCode.t.sol index 3978cfc335f5f..9499a9ff7f6fc 100644 --- a/testdata/default/cheats/DeployCode.t.sol +++ b/testdata/default/cheats/DeployCode.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract TestContract {} @@ -36,9 +35,7 @@ contract TestPayableContractWithArgs { } } -contract DeployCodeTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract DeployCodeTest is Test { address public constant overrideAddress = 0x0000000000000000000000000000000000000064; event Payload(address sender, address target, bytes data); diff --git a/testdata/default/cheats/Derive.t.sol b/testdata/default/cheats/Derive.t.sol index c27456c6ec487..5ed5bd709c5e3 100644 --- a/testdata/default/cheats/Derive.t.sol +++ b/testdata/default/cheats/Derive.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract DeriveTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract DeriveTest is Test { function testDerive() public { string memory mnemonic = "test test test test test test test test test test test junk"; diff --git a/testdata/default/cheats/EnsNamehash.t.sol b/testdata/default/cheats/EnsNamehash.t.sol index 965d505006060..94af39a8eb784 100644 --- a/testdata/default/cheats/EnsNamehash.t.sol +++ b/testdata/default/cheats/EnsNamehash.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract EnsNamehashTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract EnsNamehashTest is Test { function testEnsNamehash() public { assertEq(vm.ensNamehash(""), 0x0000000000000000000000000000000000000000000000000000000000000000); assertEq(vm.ensNamehash("eth"), 0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae); diff --git a/testdata/default/cheats/Env.t.sol b/testdata/default/cheats/Env.t.sol index 7edb35dff13ff..641167f3dfb14 100644 --- a/testdata/default/cheats/Env.t.sol +++ b/testdata/default/cheats/Env.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract EnvTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract EnvTest is Test { function testSetEnv() public { string memory key = "_foundryCheatcodeSetEnvTestKey"; string memory val = "_foundryCheatcodeSetEnvTestVal"; diff --git a/testdata/default/cheats/Etch.t.sol b/testdata/default/cheats/Etch.t.sol index 5e93dfb81213b..6bd4c28914052 100644 --- a/testdata/default/cheats/Etch.t.sol +++ b/testdata/default/cheats/Etch.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract EtchTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract EtchTest is Test { function testEtch() public { address target = address(7070707); bytes memory code = hex"1010"; diff --git a/testdata/default/cheats/ExpectCall.t.sol b/testdata/default/cheats/ExpectCall.t.sol index 01a95b4277e01..d4f2a3fb593fa 100644 --- a/testdata/default/cheats/ExpectCall.t.sol +++ b/testdata/default/cheats/ExpectCall.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract Contract { function numberA() public pure returns (uint256) { @@ -60,9 +59,7 @@ contract ProxyWithDelegateCall { } } -contract ExpectCallTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract ExpectCallTest is Test { function exposed_callTargetNTimes(Contract target, uint256 a, uint256 b, uint256 times) public { for (uint256 i = 0; i < times; i++) { target.add(a, b); @@ -206,9 +203,7 @@ contract ExpectCallTest is DSTest { } } -contract ExpectCallCountTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract ExpectCallCountTest is Test { function testExpectCallCountWithData() public { Contract target = new Contract(); vm.expectCall(address(target), abi.encodeWithSelector(Contract.add.selector, 1, 2), 3); @@ -332,9 +327,7 @@ contract ExpectCallCountTest is DSTest { } } -contract ExpectCallMixedTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract ExpectCallMixedTest is Test { function exposed_callTargetNTimes(Contract target, uint256 a, uint256 b, uint256 times) public { for (uint256 i = 0; i < times; i++) { target.add(1, 2); diff --git a/testdata/default/cheats/ExpectCreate.t.sol b/testdata/default/cheats/ExpectCreate.t.sol index a922d01b92bac..f416c645b3424 100644 --- a/testdata/default/cheats/ExpectCreate.t.sol +++ b/testdata/default/cheats/ExpectCreate.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract Contract { function add(uint256 a, uint256 b) public pure returns (uint256) { @@ -20,8 +19,7 @@ contract ContractDeployer { } } -contract ExpectCreateTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +contract ExpectCreateTest is Test { bytes bytecode = vm.getDeployedCode("cheats/ExpectCreate.t.sol:Contract"); function testExpectCreate() public { diff --git a/testdata/default/cheats/ExpectEmit.t.sol b/testdata/default/cheats/ExpectEmit.t.sol index ca91513443d21..516ac1079476c 100644 --- a/testdata/default/cheats/ExpectEmit.t.sol +++ b/testdata/default/cheats/ExpectEmit.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract Emitter { uint256 public thing; @@ -115,8 +114,7 @@ contract LowLevelCaller { function g() public {} } -contract ExpectEmitTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +contract ExpectEmitTest is Test { Emitter emitter; event Something(uint256 indexed topic1, uint256 indexed topic2, uint256 indexed topic3, uint256 data); @@ -416,8 +414,7 @@ contract ExpectEmitTest is DSTest { // } } -contract ExpectEmitCountTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +contract ExpectEmitCountTest is Test { Emitter emitter; event Something(uint256 indexed topic1, uint256 indexed topic2, uint256 indexed topic3, uint256 data); diff --git a/testdata/default/cheats/ExpectRevert.t.sol b/testdata/default/cheats/ExpectRevert.t.sol index 1b70af1188765..f8fcf3d621318 100644 --- a/testdata/default/cheats/ExpectRevert.t.sol +++ b/testdata/default/cheats/ExpectRevert.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract Reverter { error CustomError(); @@ -71,9 +70,7 @@ contract Dummy { } } -contract ExpectRevertTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract ExpectRevertTest is Test { function shouldRevert() internal { revert(); } @@ -263,9 +260,7 @@ contract DContract { } } -contract ExpectRevertWithReverterTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract ExpectRevertWithReverterTest is Test { error CContractError(string reason); AContract aContract; @@ -312,9 +307,7 @@ contract ExpectRevertWithReverterTest is DSTest { } } -contract ExpectRevertCount is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract ExpectRevertCount is Test { function testRevertCountAny() public { uint64 count = 3; Reverter reverter = new Reverter(); @@ -395,9 +388,7 @@ contract ExpectRevertCount is DSTest { } } -contract ExpectRevertCountWithReverter is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract ExpectRevertCountWithReverter is Test { function testRevertCountWithReverter() public { uint64 count = 2; Reverter reverter = new Reverter(); diff --git a/testdata/default/cheats/Fee.t.sol b/testdata/default/cheats/Fee.t.sol index 120627c0004e9..d96fa6f9b6af7 100644 --- a/testdata/default/cheats/Fee.t.sol +++ b/testdata/default/cheats/Fee.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract FeeTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract FeeTest is Test { function testFee() public { vm.fee(10); assertEq(block.basefee, 10, "fee failed"); diff --git a/testdata/default/cheats/Ffi.t.sol b/testdata/default/cheats/Ffi.t.sol index 23ac54e6ace12..6c84bdf893c29 100644 --- a/testdata/default/cheats/Ffi.t.sol +++ b/testdata/default/cheats/Ffi.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract FfiTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract FfiTest is Test { function testFfi() public { string[] memory inputs = new string[](3); inputs[0] = "bash"; diff --git a/testdata/default/cheats/Fork.t.sol b/testdata/default/cheats/Fork.t.sol index 2f2e627de131a..281a27a0b868c 100644 --- a/testdata/default/cheats/Fork.t.sol +++ b/testdata/default/cheats/Fork.t.sol @@ -1,19 +1,17 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; interface IWETH { function deposit() external payable; function balanceOf(address) external view returns (uint256); } -contract ForkTest is DSTest { +contract ForkTest is Test { 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; diff --git a/testdata/default/cheats/Fork2.t.sol b/testdata/default/cheats/Fork2.t.sol index d0703ce7fa6ce..037d4e0fa9528 100644 --- a/testdata/default/cheats/Fork2.t.sol +++ b/testdata/default/cheats/Fork2.t.sol @@ -1,9 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "../logs/console.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; struct MyStruct { uint256 value; @@ -27,9 +25,7 @@ contract MyContract { } } -contract ForkTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract ForkTest is Test { uint256 mainnetFork; uint256 optimismFork; @@ -150,7 +146,7 @@ contract ForkTest is DSTest { assertEq(dummy.val(), expectedValue); } - // checks diagnostic + /// forge-config: default.allow_internal_expect_revert = true function testNonExistingContractRevert() public { vm.selectFork(mainnetFork); DummyContract dummy = new DummyContract(); @@ -164,7 +160,8 @@ contract ForkTest is DSTest { assertEq(dummyAddress, address(dummy)); // this will revert since `dummy` does not exists on the currently active fork - string memory msg2 = dummy.hello(); + vm.expectRevert(); + dummy.noop(); } struct EthGetLogsJsonParseable { @@ -245,6 +242,8 @@ contract ForkTest is DSTest { contract DummyContract { uint256 public val; + function noop() external pure {} + function hello() external view returns (string memory) { return "hello"; } diff --git a/testdata/default/cheats/Fs.t.sol b/testdata/default/cheats/Fs.t.sol index b4882525944cf..80b89d7d69931 100644 --- a/testdata/default/cheats/Fs.t.sol +++ b/testdata/default/cheats/Fs.t.sol @@ -1,11 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; -contract FsTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +contract FsTest is Test { bytes constant FOUNDRY_TOML_ACCESS_ERR = "access to foundry.toml is not allowed"; bytes constant FOUNDRY_READ_ERR = "the path /etc/hosts is not allowed to be accessed for read operations"; bytes constant FOUNDRY_READ_DIR_ERR = "the path /etc is not allowed to be accessed for read operations"; @@ -42,7 +40,7 @@ contract FsTest is DSTest { } function testWriteFile() public { - string memory path = "fixtures/File/write_file.txt"; + string memory path = "fixtures/File/ignored/write_file.txt"; string memory data = "hello writable world"; vm.writeFile(path, data); @@ -58,7 +56,7 @@ contract FsTest is DSTest { function testCopyFile() public { string memory from = "fixtures/File/read.txt"; - string memory to = "fixtures/File/copy.txt"; + string memory to = "fixtures/File/ignored/copy.txt"; uint64 copied = vm.copyFile(from, to); assertEq(vm.fsMetadata(to).length, uint256(copied)); assertEq(vm.readFile(from), vm.readFile(to)); @@ -66,7 +64,7 @@ contract FsTest is DSTest { } function testWriteLine() public { - string memory path = "fixtures/File/write_line.txt"; + string memory path = "fixtures/File/ignored/write_line.txt"; string memory line1 = "first line"; vm.writeLine(path, line1); @@ -91,7 +89,7 @@ contract FsTest is DSTest { } function testRemoveFile() public { - string memory path = "fixtures/File/remove_file.txt"; + string memory path = "fixtures/File/ignored/remove_file.txt"; string memory data = "hello writable world"; vm.writeFile(path, data); diff --git a/testdata/default/cheats/GasMetering.t.sol b/testdata/default/cheats/GasMetering.t.sol index 3cb105d236f02..fbde54741c624 100644 --- a/testdata/default/cheats/GasMetering.t.sol +++ b/testdata/default/cheats/GasMetering.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract B { function a() public returns (uint256) { @@ -10,9 +9,7 @@ contract B { } } -contract GasMeteringTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract GasMeteringTest is Test { function testGasMetering() public { uint256 gas_start = gasleft(); @@ -40,6 +37,7 @@ contract GasMeteringTest is DSTest { function testGasMeteringExternal() public { B b = new B(); + uint256 gas_start = gasleft(); b.a(); diff --git a/testdata/default/cheats/GetArtifactPath.t.sol b/testdata/default/cheats/GetArtifactPath.t.sol index 4b0df4ba6e6ec..7a2e1335d0c04 100644 --- a/testdata/default/cheats/GetArtifactPath.t.sol +++ b/testdata/default/cheats/GetArtifactPath.t.sol @@ -1,20 +1,16 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity =0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract DummyForGetArtifactPath {} -contract GetArtifactPathTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract GetArtifactPathTest is Test { function testGetArtifactPathByCode() public { - DummyForGetArtifactPath dummy = new DummyForGetArtifactPath(); bytes memory dummyCreationCode = type(DummyForGetArtifactPath).creationCode; string memory path = vm.getArtifactPathByCode(dummyCreationCode); - assertTrue(vm.contains(path, "/out/default/GetArtifactPath.t.sol/DummyForGetArtifactPath.json")); + assertTrue(vm.contains(path, "/out/GetArtifactPath.t.sol/DummyForGetArtifactPath.json")); } function testGetArtifactPathByDeployedCode() public { @@ -22,6 +18,6 @@ contract GetArtifactPathTest is DSTest { bytes memory dummyRuntimeCode = address(dummy).code; string memory path = vm.getArtifactPathByDeployedCode(dummyRuntimeCode); - assertTrue(vm.contains(path, "/out/default/GetArtifactPath.t.sol/DummyForGetArtifactPath.json")); + assertTrue(vm.contains(path, "/out/GetArtifactPath.t.sol/DummyForGetArtifactPath.json")); } } diff --git a/testdata/default/cheats/GetBlockTimestamp.t.sol b/testdata/default/cheats/GetBlockTimestamp.t.sol index 816bc0d1ef89e..65bda02052764 100644 --- a/testdata/default/cheats/GetBlockTimestamp.t.sol +++ b/testdata/default/cheats/GetBlockTimestamp.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract GetBlockTimestampTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract GetBlockTimestampTest is Test { function testGetTimestamp() public { uint256 timestamp = vm.getBlockTimestamp(); assertEq(timestamp, 1, "timestamp should be 1"); diff --git a/testdata/default/cheats/GetChain.t.sol b/testdata/default/cheats/GetChain.t.sol index 15923612cfc60..ca6e1a5c284cf 100644 --- a/testdata/default/cheats/GetChain.t.sol +++ b/testdata/default/cheats/GetChain.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.13; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract GetChainTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract GetChainTest is Test { function testGetMainnet() public { // Test mainnet Vm.Chain memory mainnet = vm.getChain("mainnet"); diff --git a/testdata/default/cheats/GetCode.t.sol b/testdata/default/cheats/GetCode.t.sol index 6020e4f1fd5bb..514ac66b9d0b3 100644 --- a/testdata/default/cheats/GetCode.t.sol +++ b/testdata/default/cheats/GetCode.t.sol @@ -1,16 +1,13 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity =0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract TestContract {} contract TestContractGetCode {} -contract GetCodeTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract GetCodeTest is Test { function testGetCode() public { bytes memory fullPath = vm.getCode("fixtures/GetCode/WorkingContract.json"); //bytes memory fileOnly = vm.getCode("WorkingContract.sol"); @@ -73,6 +70,7 @@ contract GetCodeTest is DSTest { /// forge-config: default.allow_internal_expect_revert = true function testRevertIfGetUnlinked() public { + vm.skip(true, "artifacts are always linked now"); vm.expectRevert("vm.getCode: no matching artifact found"); vm.getCode("UnlinkedContract.sol"); } diff --git a/testdata/default/cheats/GetDeployedCode.t.sol b/testdata/default/cheats/GetDeployedCode.t.sol index 295d2ae8f3f38..a33a13d47805c 100644 --- a/testdata/default/cheats/GetDeployedCode.t.sol +++ b/testdata/default/cheats/GetDeployedCode.t.sol @@ -1,14 +1,11 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity =0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract TestContract {} -contract GetDeployedCodeTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract GetDeployedCodeTest is Test { address public constant overrideAddress = 0x0000000000000000000000000000000000000064; event Payload(address sender, address target, bytes data); diff --git a/testdata/default/cheats/GetFoundryVersion.t.sol b/testdata/default/cheats/GetFoundryVersion.t.sol index ac30bb8491874..6139b8b6b6a5e 100644 --- a/testdata/default/cheats/GetFoundryVersion.t.sol +++ b/testdata/default/cheats/GetFoundryVersion.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract GetFoundryVersionTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract GetFoundryVersionTest is Test { function testGetFoundryVersion() public view { // (e.g. 0.3.0-nightly+3cb96bde9b.1737036656.debug) string memory fullVersionString = vm.getFoundryVersion(); diff --git a/testdata/default/cheats/GetLabel.t.sol b/testdata/default/cheats/GetLabel.t.sol index c5a5638d36752..b5ccc64533862 100644 --- a/testdata/default/cheats/GetLabel.t.sol +++ b/testdata/default/cheats/GetLabel.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract GetLabelTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract GetLabelTest is Test { function testGetLabel() public { // Label an address. vm.label(address(1), "Sir Address the 1st"); diff --git a/testdata/default/cheats/GetNonce.t.sol b/testdata/default/cheats/GetNonce.t.sol index d4043a59992a8..a786fd496ff94 100644 --- a/testdata/default/cheats/GetNonce.t.sol +++ b/testdata/default/cheats/GetNonce.t.sol @@ -1,14 +1,11 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract Foo {} -contract GetNonceTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract GetNonceTest is Test { function testGetNonce() public { uint64 nonce1 = vm.getNonce(address(this)); new Foo(); diff --git a/testdata/default/cheats/GetRawBlockHeader.t.sol b/testdata/default/cheats/GetRawBlockHeader.t.sol index 9dcd2fc0d39c4..54600149863a0 100644 --- a/testdata/default/cheats/GetRawBlockHeader.t.sol +++ b/testdata/default/cheats/GetRawBlockHeader.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract GetRawBlockHeaderTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract GetRawBlockHeaderTest is Test { function testGetRawBlockHeaderWithFork() public { vm.createSelectFork("mainnet"); assertEq( diff --git a/testdata/default/cheats/GetStorageSlots.t.sol b/testdata/default/cheats/GetStorageSlots.t.sol index 4ac6f77d462fd..f61638ac51ea1 100644 --- a/testdata/default/cheats/GetStorageSlots.t.sol +++ b/testdata/default/cheats/GetStorageSlots.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract StorageContract { // Simple variables - 1 slot each @@ -44,8 +43,7 @@ contract StorageContract { } } -contract GetStorageSlotsTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +contract GetStorageSlotsTest is Test { StorageContract storageContract; function setUp() public { diff --git a/testdata/default/cheats/Json.t.sol b/testdata/default/cheats/Json.t.sol index b7aefae736e9a..c187e07465bb1 100644 --- a/testdata/default/cheats/Json.t.sol +++ b/testdata/default/cheats/Json.t.sol @@ -1,9 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; -import "../logs/console.sol"; +import "utils/Test.sol"; library JsonStructs { address constant HEVM_ADDRESS = address(bytes20(uint160(uint256(keccak256("hevm cheat code"))))); @@ -66,7 +64,7 @@ library JsonStructs { } } -contract ParseJsonTest is DSTest { +contract ParseJsonTest is Test { using JsonStructs for *; struct FlatJson { @@ -88,7 +86,6 @@ contract ParseJsonTest is DSTest { string name; } - Vm constant vm = Vm(HEVM_ADDRESS); string json; function setUp() public { @@ -328,9 +325,7 @@ contract ParseJsonTest is DSTest { } } -contract WriteJsonTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract WriteJsonTest is Test { string json1; string json2; diff --git a/testdata/default/cheats/Label.t.sol b/testdata/default/cheats/Label.t.sol index 4ff5d3860bed0..7c1ebd02d2443 100644 --- a/testdata/default/cheats/Label.t.sol +++ b/testdata/default/cheats/Label.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract LabelTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract LabelTest is Test { function testLabel() public { vm.label(address(1), "Sir Address the 1st"); } diff --git a/testdata/default/cheats/Load.t.sol b/testdata/default/cheats/Load.t.sol index 06f4b5bd52718..dcdd145c7c8f7 100644 --- a/testdata/default/cheats/Load.t.sol +++ b/testdata/default/cheats/Load.t.sol @@ -1,15 +1,13 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract Storage { uint256 slot0 = 10; } -contract LoadTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +contract LoadTest is Test { uint256 slot0 = 20; Storage store; diff --git a/testdata/default/cheats/Mapping.t.sol b/testdata/default/cheats/Mapping.t.sol index 82477150ae9ca..7b0eb11ccb32d 100644 --- a/testdata/default/cheats/Mapping.t.sol +++ b/testdata/default/cheats/Mapping.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract RecordMapping { int256 length; @@ -18,9 +17,7 @@ contract RecordMapping { } } -contract RecordMappingTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract RecordMappingTest is Test { function testRecordMapping() public { RecordMapping target = new RecordMapping(); diff --git a/testdata/default/cheats/MemSafety.t.sol b/testdata/default/cheats/MemSafety.t.sol index 9bb282538ddfe..953ca07e85e03 100644 --- a/testdata/default/cheats/MemSafety.t.sol +++ b/testdata/default/cheats/MemSafety.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract MemSafetyTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract MemSafetyTest is Test { //////////////////////////////////////////////////////////////// // MSTORE // //////////////////////////////////////////////////////////////// diff --git a/testdata/default/cheats/MockCall.t.sol b/testdata/default/cheats/MockCall.t.sol index f11fd20984571..e2ac74d6f70fa 100644 --- a/testdata/default/cheats/MockCall.t.sol +++ b/testdata/default/cheats/MockCall.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract Mock { uint256 state = 0; @@ -56,9 +55,7 @@ contract NestedMockDelegateCall { } } -contract MockCallTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract MockCallTest is Test { function testMockGetters() public { Mock target = new Mock(); @@ -183,9 +180,7 @@ contract MockCallTest is DSTest { } } -contract MockCallRevertTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract MockCallRevertTest is Test { error TestError(bytes msg); bytes constant ERROR_MESSAGE = "ERROR_MESSAGE"; diff --git a/testdata/default/cheats/MockCalls.t.sol b/testdata/default/cheats/MockCalls.t.sol index 2bd4d8bd9ea2e..e0f5eef151db6 100644 --- a/testdata/default/cheats/MockCalls.t.sol +++ b/testdata/default/cheats/MockCalls.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract MockCallsTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract MockCallsTest is Test { function testMockCallsLastShouldPersist() public { address mockUser = vm.addr(vm.randomUint()); address mockErc20 = vm.addr(vm.randomUint()); diff --git a/testdata/default/cheats/MockFunction.t.sol b/testdata/default/cheats/MockFunction.t.sol index 6d670024b2053..3defa8cfd3580 100644 --- a/testdata/default/cheats/MockFunction.t.sol +++ b/testdata/default/cheats/MockFunction.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract MockFunctionContract { uint256 public a; @@ -28,10 +27,9 @@ contract ModelMockFunctionContract { } } -contract MockFunctionTest is DSTest { +contract MockFunctionTest is Test { MockFunctionContract my_contract; ModelMockFunctionContract model_contract; - Vm vm = Vm(HEVM_ADDRESS); function setUp() public { my_contract = new MockFunctionContract(); diff --git a/testdata/default/cheats/Nonce.t.sol b/testdata/default/cheats/Nonce.t.sol index 312c2b4d7edcc..7b7f7553e7854 100644 --- a/testdata/default/cheats/Nonce.t.sol +++ b/testdata/default/cheats/Nonce.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract Counter { uint256 public count; @@ -12,9 +11,8 @@ contract Counter { } } -contract NonceIsolatedTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +/// forge-config: default.isolate = true +contract NonceIsolatedTest is Test { function testIncrementNonce() public { address bob = address(14); vm.startPrank(bob); diff --git a/testdata/default/cheats/Parse.t.sol b/testdata/default/cheats/Parse.t.sol index 65e7561d104de..2736aa8ade7b6 100644 --- a/testdata/default/cheats/Parse.t.sol +++ b/testdata/default/cheats/Parse.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract ParseTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract ParseTest is Test { function testParseBytes() public { bytes memory testBytes = hex"7109709ECfa91a80626fF3989D68f67F5b1DD12D"; diff --git a/testdata/default/cheats/Prank.t.sol b/testdata/default/cheats/Prank.t.sol index 151f0d8306776..e8124b2475e16 100644 --- a/testdata/default/cheats/Prank.t.sol +++ b/testdata/default/cheats/Prank.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract Victim { function assertCallerAndOrigin( @@ -107,9 +106,7 @@ contract ProxyTest { address public sender; } -contract PrankTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract PrankTest is Test { function testPrankDelegateCallPrank2() public { ProxyTest proxy = new ProxyTest(); ImplementationTest impl = new ImplementationTest(); @@ -551,9 +548,7 @@ contract PrankTest is DSTest { } } -contract Issue9990 is DSTest { - Vm constant vm = Vm(address(bytes20(uint160(uint256(keccak256("hevm cheat code")))))); - +contract Issue9990 is Test { function testDelegatePrank() external { A a = new A(); vm.etch(address(0x11111), hex"11"); @@ -600,9 +595,7 @@ contract Counter { } } -contract Issue10528 is DSTest { - Vm constant vm = Vm(address(bytes20(uint160(uint256(keccak256("hevm cheat code")))))); - +contract Issue10528 is Test { function testStartPrankOnContractCreation() external { vm.startPrank(address(0x22222)); Counter counter = new Counter(); diff --git a/testdata/default/cheats/Prevrandao.t.sol b/testdata/default/cheats/Prevrandao.t.sol index aab8e326c43ce..ff4d8b48b8c8d 100644 --- a/testdata/default/cheats/Prevrandao.t.sol +++ b/testdata/default/cheats/Prevrandao.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract PrevrandaoTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract PrevrandaoTest is Test { function testPrevrandao() public { assertEq(block.prevrandao, 0); vm.prevrandao(uint256(10)); diff --git a/testdata/default/cheats/ProjectRoot.t.sol b/testdata/default/cheats/ProjectRoot.t.sol index cff3d83751d66..8835d2192cbfc 100644 --- a/testdata/default/cheats/ProjectRoot.t.sol +++ b/testdata/default/cheats/ProjectRoot.t.sol @@ -1,15 +1,19 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; -contract ProjectRootTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +contract ProjectRootTest is Test { bytes public manifestDirBytes; function testProjectRoot() public { - manifestDirBytes = bytes(vm.envString("CARGO_MANIFEST_DIR")); + // .../crates/forge + string memory manifestDir = vm.envOr("CARGO_MANIFEST_DIR", string("")); + if (bytes(manifestDir).length == 0) { + vm.skip(true, "CARGO_MANIFEST_DIR environment variable is not set"); + } + manifestDirBytes = bytes(manifestDir); + for (uint256 i = 0; i < 7; i++) { manifestDirBytes.pop(); } @@ -20,6 +24,10 @@ contract ProjectRootTest is DSTest { } bytes memory expectedRootDir = abi.encodePacked(manifestDirBytes, "ata"); - assertEq(vm.projectRoot(), string(expectedRootDir)); + assertEq(normalizePath(vm.projectRoot()), normalizePath(string(expectedRootDir))); + } + + function normalizePath(string memory path) internal pure returns (string memory) { + return vm.replace(path, "\\", "/"); } } diff --git a/testdata/default/cheats/Prompt.t.sol b/testdata/default/cheats/Prompt.t.sol index fa60f6740698e..5505629da15ba 100644 --- a/testdata/default/cheats/Prompt.t.sol +++ b/testdata/default/cheats/Prompt.t.sol @@ -1,15 +1,14 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; -import "../logs/console.sol"; - -contract PromptTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +// All `prompt` functions should revert in CI and testing environments either +// with a timeout or because no terminal is available. +contract PromptTest is Test { function testPrompt_revertNotATerminal() public { - // should revert in CI and testing environments either with timeout or because no terminal is available + checkTty(); + vm._expectCheatcodeRevert(); vm.prompt("test"); @@ -21,12 +20,22 @@ contract PromptTest is DSTest { } function testPrompt_Address() public { + checkTty(); + vm._expectCheatcodeRevert(); address test = vm.promptAddress("test"); } function testPrompt_Uint() public { + checkTty(); + vm._expectCheatcodeRevert(); uint256 test = vm.promptUint("test"); } + + function checkTty() internal { + if (!vm.envOr("CI", false)) { + vm.skip(true, "min timeout is 1s, don't test it"); + } + } } diff --git a/testdata/default/cheats/RandomAddress.t.sol b/testdata/default/cheats/RandomAddress.t.sol index 61510ed4eaaac..043884ed0a014 100644 --- a/testdata/default/cheats/RandomAddress.t.sol +++ b/testdata/default/cheats/RandomAddress.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract RandomAddress is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract RandomAddress is Test { function testRandomAddress() public { vm.randomAddress(); } diff --git a/testdata/default/cheats/RandomBytes.t.sol b/testdata/default/cheats/RandomBytes.t.sol index dbc03a6ccfb8f..4cdc08a61604c 100644 --- a/testdata/default/cheats/RandomBytes.t.sol +++ b/testdata/default/cheats/RandomBytes.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract RandomBytes is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract RandomBytes is Test { function testRandomBytes4() public { vm.randomBytes4(); } diff --git a/testdata/default/cheats/RandomCheatcodes.t.sol b/testdata/default/cheats/RandomCheatcodes.t.sol index c42b4310012f1..bd1968000eab7 100644 --- a/testdata/default/cheats/RandomCheatcodes.t.sol +++ b/testdata/default/cheats/RandomCheatcodes.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract RandomCheatcodesTest is DSTest { - Vm vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract RandomCheatcodesTest is Test { int128 constant min = -170141183460469231731687303715884105728; int128 constant max = 170141183460469231731687303715884105727; @@ -57,9 +54,7 @@ contract RandomCheatcodesTest is DSTest { } } -contract RandomBytesTest is DSTest { - Vm vm = Vm(HEVM_ADDRESS); - +contract RandomBytesTest is Test { bytes1 local_byte; bytes local_bytes; diff --git a/testdata/default/cheats/RandomUint.t.sol b/testdata/default/cheats/RandomUint.t.sol index c0021030d0d1e..8e0b402386133 100644 --- a/testdata/default/cheats/RandomUint.t.sol +++ b/testdata/default/cheats/RandomUint.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract RandomUint is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract RandomUint is Test { function testRandomUint() public { vm.randomUint(); } diff --git a/testdata/default/cheats/ReadCallers.t.sol b/testdata/default/cheats/ReadCallers.t.sol index dbd198a2d93e8..7bef8c502a091 100644 --- a/testdata/default/cheats/ReadCallers.t.sol +++ b/testdata/default/cheats/ReadCallers.t.sol @@ -1,16 +1,13 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract Target { function consumeNewCaller() external {} } -contract ReadCallersTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract ReadCallersTest is Test { function testReadCallersWithNoActivePrankOrBroadcast() public { address expectedSender = msg.sender; address expectedTxOrigin = tx.origin; diff --git a/testdata/default/cheats/Record.t.sol b/testdata/default/cheats/Record.t.sol index c3029d5f54205..6525092803303 100644 --- a/testdata/default/cheats/Record.t.sol +++ b/testdata/default/cheats/Record.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract RecordAccess { function record() public returns (NestedRecordAccess) { @@ -25,9 +24,7 @@ contract NestedRecordAccess { } } -contract RecordTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract RecordTest is Test { function testRecordAccess() public { RecordAccess target = new RecordAccess(); diff --git a/testdata/default/cheats/RecordAccountAccesses.t.sol b/testdata/default/cheats/RecordAccountAccesses.t.sol index 88f795fafef99..fee8ebbc361c8 100644 --- a/testdata/default/cheats/RecordAccountAccesses.t.sol +++ b/testdata/default/cheats/RecordAccountAccesses.t.sol @@ -1,9 +1,7 @@ // SPDX-License-Identifier: Unlicense pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; -import "../logs/console.sol"; +import "utils/Test.sol"; /// @notice Helper contract with a construction that makes a call to itself then /// optionally reverts if zero-length data is passed @@ -124,13 +122,13 @@ contract NestedRunner { /// Helper contract that uses all three EXT* opcodes on a given address contract ExtChecker { - function checkExts(address a) external { + function checkExts(address a) external returns (bytes memory out) { assembly { - let x := extcodesize(a) - let y := extcodehash(a) - extcodecopy(a, x, y, 0) - // sstore to check that storage accesses are correctly stored in a new access with a "resume" context - sstore(0, balance(a)) + mstore(out, mul(0x20, 4)) + mstore(add(out, 0x20), extcodesize(a)) + mstore(add(out, 0x40), extcodehash(a)) + extcodecopy(a, 0, 0x60, 0x20) + mstore(add(out, 0x80), balance(a)) } } } @@ -203,8 +201,7 @@ contract Proxy { } /// @notice Test that the cheatcode correctly records account accesses -contract RecordAccountAccessesTest is DSTest { - Vm constant cheats = Vm(HEVM_ADDRESS); +contract RecordAccountAccessesTest is Test { NestedRunner runner; NestedStorer nestedStorer; Create2or create2or; @@ -225,9 +222,9 @@ contract RecordAccountAccessesTest is DSTest { StorageAccessor one = test1; Proxy proxy = new Proxy(address(one)); - cheats.startStateDiffRecording(); + vm.startStateDiffRecording(); address(proxy).call(abi.encodeCall(StorageAccessor.read, bytes32(uint256(1234)))); - Vm.AccountAccess[] memory called = filterExtcodesizeForLegacyTests(cheats.stopAndReturnStateDiff()); + Vm.AccountAccess[] memory called = filterExtcodesizeForLegacyTests(vm.stopAndReturnStateDiff()); assertEq(called.length, 2, "incorrect length"); @@ -255,24 +252,24 @@ contract RecordAccountAccessesTest is DSTest { function testStorageAccesses() public { StorageAccessor one = test1; StorageAccessor two = test2; - cheats.startStateDiffRecording(); + vm.startStateDiffRecording(); one.read(bytes32(uint256(1234))); one.write(bytes32(uint256(1235)), bytes32(uint256(5678))); two.write(bytes32(uint256(5678)), bytes32(uint256(123469))); two.write(bytes32(uint256(5678)), bytes32(uint256(1234))); - string memory diffs = cheats.getStateDiff(); + string memory diffs = vm.getStateDiff(); assertEq( "0x5991A2dF15A8F6A256D3Ec51E99254Cd3fb576A9\ncontract: default/cheats/RecordAccountAccesses.t.sol:StorageAccessor\n- state diff:\n@ 0x00000000000000000000000000000000000000000000000000000000000004d3: 0x0000000000000000000000000000000000000000000000000000000000000000 \xE2\x86\x92 0x000000000000000000000000000000000000000000000000000000000000162e\n\n0xc7183455a4C133Ae270771860664b6B7ec320bB1\ncontract: default/cheats/RecordAccountAccesses.t.sol:StorageAccessor\n- state diff:\n@ 0x000000000000000000000000000000000000000000000000000000000000162e: 0x0000000000000000000000000000000000000000000000000000000000000000 \xE2\x86\x92 0x00000000000000000000000000000000000000000000000000000000000004d2\n\n", diffs ); - string memory diffsJson = cheats.getStateDiffJson(); + string memory diffsJson = vm.getStateDiffJson(); assertEq( '{"0x5991a2df15a8f6a256d3ec51e99254cd3fb576a9":{"label":null,"contract":"default/cheats/RecordAccountAccesses.t.sol:StorageAccessor","balanceDiff":null,"nonceDiff":null,"stateDiff":{"0x00000000000000000000000000000000000000000000000000000000000004d3":{"previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","newValue":"0x000000000000000000000000000000000000000000000000000000000000162e"}}},"0xc7183455a4c133ae270771860664b6b7ec320bb1":{"label":null,"contract":"default/cheats/RecordAccountAccesses.t.sol:StorageAccessor","balanceDiff":null,"nonceDiff":null,"stateDiff":{"0x000000000000000000000000000000000000000000000000000000000000162e":{"previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","newValue":"0x00000000000000000000000000000000000000000000000000000000000004d2"}}}}', diffsJson ); - Vm.AccountAccess[] memory called = filterExtcodesizeForLegacyTests(cheats.stopAndReturnStateDiff()); + Vm.AccountAccess[] memory called = filterExtcodesizeForLegacyTests(vm.stopAndReturnStateDiff()); assertEq(called.length, 4, "incorrect length"); assertEq(called[0].storageAccesses.length, 1, "incorrect storage length"); @@ -334,7 +331,7 @@ contract RecordAccountAccessesTest is DSTest { /// @notice Test that basic account accesses are correctly recorded function testRecordAccountAccesses() public { - cheats.startStateDiffRecording(); + vm.startStateDiffRecording(); (bool succ,) = address(1234).call(""); (succ,) = address(5678).call{value: 1 ether}(""); @@ -343,7 +340,7 @@ contract RecordAccountAccessesTest is DSTest { // contract calls to self in constructor SelfCaller caller = new SelfCaller{value: 2 ether}("hello2 world2"); - string memory callerAddress = cheats.toString(address(caller)); + string memory callerAddress = vm.toString(address(caller)); string memory expectedStateDiff = "0x000000000000000000000000000000000000162e\n- balance diff: 0 \xE2\x86\x92 1000000000000000000\n\n"; expectedStateDiff = string.concat(expectedStateDiff, callerAddress); @@ -353,9 +350,9 @@ contract RecordAccountAccessesTest is DSTest { expectedStateDiff, "\n- balance diff: 0 \xE2\x86\x92 2000000000000000000\n- nonce diff: 0 \xE2\x86\x92 1\n\n" ); - assertEq(expectedStateDiff, cheats.getStateDiff()); + assertEq(expectedStateDiff, vm.getStateDiff()); - Vm.AccountAccess[] memory called = filterExtcodesizeForLegacyTests(cheats.stopAndReturnStateDiff()); + Vm.AccountAccess[] memory called = filterExtcodesizeForLegacyTests(vm.stopAndReturnStateDiff()); assertEq(called.length, 6); assertEq( called[0], @@ -484,17 +481,17 @@ contract RecordAccountAccessesTest is DSTest { /// reverts function testRevertingCall() public { uint256 initBalance = address(this).balance; - cheats.startStateDiffRecording(); + vm.startStateDiffRecording(); try this.revertingCall{value: 1 ether}(address(1234), "") {} catch {} assertEq( "0x00000000000000000000000000000000000004d2\n- balance diff: 0 \xE2\x86\x92 100000000000000000\n\n", - cheats.getStateDiff() + vm.getStateDiff() ); assertEq( '{"0x00000000000000000000000000000000000004d2":{"label":null,"contract":null,"balanceDiff":{"previousValue":"0x0","newValue":"0x16345785d8a0000"},"nonceDiff":null,"stateDiff":{}}}', - cheats.getStateDiffJson() + vm.getStateDiffJson() ); - Vm.AccountAccess[] memory called = filterExtcodesizeForLegacyTests(cheats.stopAndReturnStateDiff()); + Vm.AccountAccess[] memory called = filterExtcodesizeForLegacyTests(vm.stopAndReturnStateDiff()); assertEq(called.length, 2); assertEq( called[0], @@ -540,14 +537,14 @@ contract RecordAccountAccessesTest is DSTest { /// @notice Test that nested account accesses are correctly recorded function testNested() public { - cheats.startStateDiffRecording(); + vm.startStateDiffRecording(); runNested(false, false); } /// @notice Test that nested account accesses are correctly recorded when /// the first call reverts function testNested_Revert() public { - cheats.startStateDiffRecording(); + vm.startStateDiffRecording(); runNested(true, false); } @@ -555,7 +552,7 @@ contract RecordAccountAccessesTest is DSTest { /// @param shouldRevert Whether the first call should revert function runNested(bool shouldRevert, bool expectFirstCall) public { try runner.run{value: 1 ether}(shouldRevert) {} catch {} - Vm.AccountAccess[] memory called = filterExtcodesizeForLegacyTests(cheats.stopAndReturnStateDiff()); + Vm.AccountAccess[] memory called = filterExtcodesizeForLegacyTests(vm.stopAndReturnStateDiff()); assertEq(called.length, 7 + toUint(expectFirstCall), "incorrect length"); uint64 startingIndex = uint64(toUint(expectFirstCall)); @@ -829,18 +826,18 @@ contract RecordAccountAccessesTest is DSTest { } function testNestedStorage() public { - cheats.startStateDiffRecording(); + vm.startStateDiffRecording(); nestedStorer.run(); - cheats.label(address(nestedStorer), "NestedStorer"); + vm.label(address(nestedStorer), "NestedStorer"); assertEq( "0x2e234DAe75C793f67A35089C9d99245E1C58470b\nlabel: NestedStorer\ncontract: default/cheats/RecordAccountAccesses.t.sol:NestedStorer\n- state diff:\n@ 0x4566fa0cd03218c55bba914d793f5e6b9113172c1f684bb5f464c08c867e8977: 0x0000000000000000000000000000000000000000000000000000000000000000 \xE2\x86\x92 0x0000000000000000000000000000000000000000000000000000000000000001\n@ 0xbf57896b60daefa2c41de2feffecfc11debd98ea8c913a5170f60e53959ac00a: 0x0000000000000000000000000000000000000000000000000000000000000000 \xE2\x86\x92 0x0000000000000000000000000000000000000000000000000000000000000001\n@ 0xc664893a982d78bbeab379feef216ff517b7ea73626b280723be1ace370364cd: 0x0000000000000000000000000000000000000000000000000000000000000000 \xE2\x86\x92 0x0000000000000000000000000000000000000000000000000000000000000001\n@ 0xdc5330afa9872081253545dca3f448752688ff1b098b38c1abe4c4cdff4b0b0e: 0x0000000000000000000000000000000000000000000000000000000000000000 \xE2\x86\x92 0x0000000000000000000000000000000000000000000000000000000000000001\n\n", - cheats.getStateDiff() + vm.getStateDiff() ); assertEq( '{"0x2e234dae75c793f67a35089c9d99245e1c58470b":{"label":"NestedStorer","contract":"default/cheats/RecordAccountAccesses.t.sol:NestedStorer","balanceDiff":null,"nonceDiff":null,"stateDiff":{"0x4566fa0cd03218c55bba914d793f5e6b9113172c1f684bb5f464c08c867e8977":{"previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","newValue":"0x0000000000000000000000000000000000000000000000000000000000000001"},"0xbf57896b60daefa2c41de2feffecfc11debd98ea8c913a5170f60e53959ac00a":{"previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","newValue":"0x0000000000000000000000000000000000000000000000000000000000000001"},"0xc664893a982d78bbeab379feef216ff517b7ea73626b280723be1ace370364cd":{"previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","newValue":"0x0000000000000000000000000000000000000000000000000000000000000001"},"0xdc5330afa9872081253545dca3f448752688ff1b098b38c1abe4c4cdff4b0b0e":{"previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","newValue":"0x0000000000000000000000000000000000000000000000000000000000000001"}}}}', - cheats.getStateDiffJson() + vm.getStateDiffJson() ); - Vm.AccountAccess[] memory called = filterExtcodesizeForLegacyTests(cheats.stopAndReturnStateDiff()); + Vm.AccountAccess[] memory called = filterExtcodesizeForLegacyTests(vm.stopAndReturnStateDiff()); assertEq(called.length, 3, "incorrect account access length"); assertEq(called[0].storageAccesses.length, 2, "incorrect run storage length"); @@ -963,14 +960,14 @@ contract RecordAccountAccessesTest is DSTest { /// @notice Test that constructor account and storage accesses are recorded, including reverts function testConstructorStorage() public { - cheats.startStateDiffRecording(); + vm.startStateDiffRecording(); address storer = address(new ConstructorStorer(false)); try create2or.create2(bytes32(0), abi.encodePacked(type(ConstructorStorer).creationCode, abi.encode(true))) {} catch {} bytes memory creationCode = abi.encodePacked(type(ConstructorStorer).creationCode, abi.encode(true)); address hypotheticalStorer = deriveCreate2Address(address(create2or), bytes32(0), keccak256(creationCode)); - Vm.AccountAccess[] memory called = filterExtcodesizeForLegacyTests(cheats.stopAndReturnStateDiff()); + Vm.AccountAccess[] memory called = filterExtcodesizeForLegacyTests(vm.stopAndReturnStateDiff()); assertEq(called.length, 3, "incorrect account access length"); assertEq(toUint(called[0].kind), toUint(Vm.AccountAccessKind.Create), "incorrect kind"); assertEq(toUint(called[1].kind), toUint(Vm.AccountAccessKind.Call), "incorrect kind"); @@ -1083,12 +1080,12 @@ contract RecordAccountAccessesTest is DSTest { /// @notice Test that constructor calls and calls made within a constructor /// are correctly recorded, even if it reverts function testCreateRevert() public { - cheats.startStateDiffRecording(); + vm.startStateDiffRecording(); bytes memory creationCode = abi.encodePacked(type(SelfCaller).creationCode, abi.encode("")); try create2or.create2(bytes32(0), creationCode) {} catch {} address hypotheticalAddress = deriveCreate2Address(address(create2or), bytes32(0), keccak256(creationCode)); - Vm.AccountAccess[] memory called = filterExtcodesizeForLegacyTests(cheats.stopAndReturnStateDiff()); + Vm.AccountAccess[] memory called = filterExtcodesizeForLegacyTests(vm.stopAndReturnStateDiff()); assertEq(called.length, 3, "incorrect length"); assertEq( called[1], @@ -1140,7 +1137,7 @@ contract RecordAccountAccessesTest is DSTest { this.startRecordingFromLowerDepth(); address a = address(new SelfDestructor{value: 1 ether}(address(this))); address b = address(new SelfDestructor{value: 1 ether}(address(bytes20("doesn't exist yet")))); - Vm.AccountAccess[] memory called = filterExtcodesizeForLegacyTests(cheats.stopAndReturnStateDiff()); + Vm.AccountAccess[] memory called = filterExtcodesizeForLegacyTests(vm.stopAndReturnStateDiff()); assertEq(called.length, 5, "incorrect length"); assertEq( called[1], @@ -1228,13 +1225,13 @@ contract RecordAccountAccessesTest is DSTest { /// @notice Asserts interaction between broadcast and recording cheatcodes function testIssue6514() public { - cheats.startStateDiffRecording(); - cheats.startBroadcast(); + vm.startStateDiffRecording(); + vm.startBroadcast(); StorageAccessor a = new StorageAccessor(); - cheats.stopBroadcast(); - Vm.AccountAccess[] memory called = filterExtcodesizeForLegacyTests(cheats.stopAndReturnStateDiff()); + vm.stopBroadcast(); + Vm.AccountAccess[] memory called = filterExtcodesizeForLegacyTests(vm.stopAndReturnStateDiff()); assertEq(called.length, 1, "incorrect length"); assertEq(toUint(called[0].kind), toUint(Vm.AccountAccessKind.Create)); assertEq(called[0].account, address(a)); @@ -1242,22 +1239,17 @@ contract RecordAccountAccessesTest is DSTest { /// @notice Test that EXT* opcodes are recorded as account accesses function testExtOpcodes() public { - cheats.startStateDiffRecording(); + vm.startStateDiffRecording(); extChecker.checkExts(address(1234)); - Vm.AccountAccess[] memory called = cheats.stopAndReturnStateDiff(); - assertEq(called.length, 7, "incorrect length"); - // initial solidity extcodesize check for calling extChecker - assertEq(toUint(called[0].kind), toUint(Vm.AccountAccessKind.Extcodesize)); + Vm.AccountAccess[] memory called = vm.stopAndReturnStateDiff(); + assertEq(called.length, 5, "incorrect length"); // call to extChecker - assertEq(toUint(called[1].kind), toUint(Vm.AccountAccessKind.Call)); + assertEq(toUint(called[0].kind), toUint(Vm.AccountAccessKind.Call)); // extChecker checks - assertEq(toUint(called[2].kind), toUint(Vm.AccountAccessKind.Extcodesize)); - assertEq(toUint(called[3].kind), toUint(Vm.AccountAccessKind.Extcodehash)); - assertEq(toUint(called[4].kind), toUint(Vm.AccountAccessKind.Extcodecopy)); - assertEq(toUint(called[5].kind), toUint(Vm.AccountAccessKind.Balance)); - // resume of extChecker to hold SSTORE access - assertEq(toUint(called[6].kind), toUint(Vm.AccountAccessKind.Resume)); - assertEq(called[6].storageAccesses.length, 1, "incorrect length"); + assertEq(toUint(called[1].kind), toUint(Vm.AccountAccessKind.Extcodesize)); + assertEq(toUint(called[2].kind), toUint(Vm.AccountAccessKind.Extcodehash)); + assertEq(toUint(called[3].kind), toUint(Vm.AccountAccessKind.Extcodecopy)); + assertEq(toUint(called[4].kind), toUint(Vm.AccountAccessKind.Balance)); } /** @@ -1287,7 +1279,7 @@ contract RecordAccountAccessesTest is DSTest { } function startRecordingFromLowerDepth() external { - cheats.startStateDiffRecording(); + vm.startStateDiffRecording(); assembly { pop(call(gas(), 1234, 0, 0, 0, 0, 0)) } @@ -1411,7 +1403,7 @@ contract RecordAccountAccessesTest is DSTest { StorageAccessor accessor = test1; // Start recording to enable storage access tracking - cheats.startStateDiffRecording(); + vm.startStateDiffRecording(); // Perform a read operation accessor.read(bytes32(uint256(789))); @@ -1423,7 +1415,7 @@ contract RecordAccountAccessesTest is DSTest { accessor.read(bytes32(uint256(123))); // Get all storage accesses - Vm.StorageAccess[] memory accesses = cheats.getStorageAccesses(); + Vm.StorageAccess[] memory accesses = vm.getStorageAccesses(); // Check we have 3 storage accesses (2 reads + 1 write) assertEq(accesses.length, 3, "should have 3 storage accesses"); diff --git a/testdata/default/cheats/RecordDebugTrace.t.sol b/testdata/default/cheats/RecordDebugTrace.t.sol index f66f701cc7ab4..f7c0b895761e4 100644 --- a/testdata/default/cheats/RecordDebugTrace.t.sol +++ b/testdata/default/cheats/RecordDebugTrace.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: Unlicense pragma solidity 0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract MStoreAndMLoadCaller { uint256 public constant expectedValueInMemory = 999; @@ -64,23 +63,21 @@ contract OutOfGas { } } -contract RecordDebugTraceTest is DSTest { - Vm constant cheats = Vm(HEVM_ADDRESS); +contract RecordDebugTraceTest is Test { /** * The goal of this test is to ensure the debug steps provide the correct OPCODE with its stack * and memory input used. The test checke MSTORE and MLOAD and ensure it records the expected * stack and memory inputs. */ - function testDebugTraceCanRecordOpcodeWithStackAndMemoryData() public { MStoreAndMLoadCaller testContract = new MStoreAndMLoadCaller(); - cheats.startDebugTraceRecording(); + vm.startDebugTraceRecording(); uint256 val = testContract.storeAndLoadValueFromMemory(); assertTrue(val == testContract.expectedValueInMemory()); - Vm.DebugStep[] memory steps = cheats.stopAndReturnDebugTraceRecording(); + Vm.DebugStep[] memory steps = vm.stopAndReturnDebugTraceRecording(); bool mstoreCalled = false; bool mloadCalled = false; @@ -118,11 +115,11 @@ contract RecordDebugTraceTest is DSTest { SecondLayer second = new SecondLayer(); FirstLayer first = new FirstLayer(second); - cheats.startDebugTraceRecording(); + vm.startDebugTraceRecording(); first.callSecondLayer(); - Vm.DebugStep[] memory steps = cheats.stopAndReturnDebugTraceRecording(); + Vm.DebugStep[] memory steps = vm.stopAndReturnDebugTraceRecording(); bool goToDepthTwo = false; bool goToDepthThree = false; @@ -149,11 +146,11 @@ contract RecordDebugTraceTest is DSTest { function testDebugTraceCanRecordOutOfGas() public { OutOfGas testContract = new OutOfGas(); - cheats.startDebugTraceRecording(); + vm.startDebugTraceRecording(); testContract.triggerOOG(); - Vm.DebugStep[] memory steps = cheats.stopAndReturnDebugTraceRecording(); + Vm.DebugStep[] memory steps = vm.stopAndReturnDebugTraceRecording(); bool isOOG = false; for (uint256 i = 0; i < steps.length; i++) { diff --git a/testdata/default/cheats/RecordLogs.t.sol b/testdata/default/cheats/RecordLogs.t.sol index 14ca8dde35e99..5927d5af23866 100644 --- a/testdata/default/cheats/RecordLogs.t.sol +++ b/testdata/default/cheats/RecordLogs.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract Emitter { event LogAnonymous(bytes data) anonymous; @@ -48,8 +47,7 @@ contract Emitterv2 { } } -contract RecordLogsTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +contract RecordLogsTest is Test { Emitter emitter; bytes32 internal seedTestData = keccak256(abi.encodePacked("Some data")); diff --git a/testdata/default/cheats/Remember.t.sol b/testdata/default/cheats/Remember.t.sol index b8dbe7e38007c..fdf00e3839f72 100644 --- a/testdata/default/cheats/Remember.t.sol +++ b/testdata/default/cheats/Remember.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract RememberTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract RememberTest is Test { function testRememberKey() public { string memory mnemonic = "test test test test test test test test test test test junk"; diff --git a/testdata/default/cheats/ResetNonce.t.sol b/testdata/default/cheats/ResetNonce.t.sol index d8c911587095c..53c8ec54b09c0 100644 --- a/testdata/default/cheats/ResetNonce.t.sol +++ b/testdata/default/cheats/ResetNonce.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract Foo { function f() external view returns (uint256) { @@ -10,8 +9,7 @@ contract Foo { } } -contract ResetNonce is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +contract ResetNonce is Test { Foo public fooContract; address barEOA; diff --git a/testdata/default/cheats/Rlp.t.sol b/testdata/default/cheats/Rlp.t.sol index c0f10f362458d..24f2ec833de7a 100644 --- a/testdata/default/cheats/Rlp.t.sol +++ b/testdata/default/cheats/Rlp.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract Rlp is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract Rlp is Test { function testToRlp() public { bytes[] memory data = new bytes[](2); data[0] = hex"01"; diff --git a/testdata/default/cheats/Roll.t.sol b/testdata/default/cheats/Roll.t.sol index 0f26e3a431d7a..38e94b2bea267 100644 --- a/testdata/default/cheats/Roll.t.sol +++ b/testdata/default/cheats/Roll.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract RollTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract RollTest is Test { function testRoll() public { vm.roll(10); assertEq(block.number, 10, "roll failed"); diff --git a/testdata/default/cheats/RpcUrls.t.sol b/testdata/default/cheats/RpcUrls.t.sol index 86f4d33b1d41c..321b5b3cbbeed 100644 --- a/testdata/default/cheats/RpcUrls.t.sol +++ b/testdata/default/cheats/RpcUrls.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract RpcUrlTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract RpcUrlTest is Test { // returns the correct url function testCanGetRpcUrl() public { string memory url = vm.rpcUrl("mainnet"); diff --git a/testdata/default/cheats/Seed.t.sol b/testdata/default/cheats/Seed.t.sol index 6db1b41da0ef3..0909c38a26f72 100644 --- a/testdata/default/cheats/Seed.t.sol +++ b/testdata/default/cheats/Seed.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract SeedTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract SeedTest is Test { function testSeedAffectsRandom() public { // Use a known seed uint256 seed = 123456789; diff --git a/testdata/default/cheats/SetBlockhash.t.sol b/testdata/default/cheats/SetBlockhash.t.sol index 1274620df41a6..2897976d11e5e 100644 --- a/testdata/default/cheats/SetBlockhash.t.sol +++ b/testdata/default/cheats/SetBlockhash.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract SetBlockhash is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract SetBlockhash is Test { function testSetBlockhash() public { bytes32 blockHash = 0x1234567890123456789012345678901234567890123456789012345678901234; vm.setBlockhash(block.number - 1, blockHash); diff --git a/testdata/default/cheats/SetNonce.t.sol b/testdata/default/cheats/SetNonce.t.sol index e0fda6aaec688..19e8a366b92ca 100644 --- a/testdata/default/cheats/SetNonce.t.sol +++ b/testdata/default/cheats/SetNonce.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract Foo { function f() external view returns (uint256) { @@ -10,8 +9,7 @@ contract Foo { } } -contract SetNonceTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +contract SetNonceTest is Test { Foo public foo; function setUp() public { diff --git a/testdata/default/cheats/SetNonceUnsafe.t.sol b/testdata/default/cheats/SetNonceUnsafe.t.sol index 0caf2b4ce7421..9f799f0829acc 100644 --- a/testdata/default/cheats/SetNonceUnsafe.t.sol +++ b/testdata/default/cheats/SetNonceUnsafe.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract Foo { function f() external view returns (uint256) { @@ -10,8 +9,7 @@ contract Foo { } } -contract SetNonceTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +contract SetNonceTest is Test { Foo public foo; function setUp() public { diff --git a/testdata/default/cheats/Setup.t.sol b/testdata/default/cheats/Setup.t.sol index 4d6e5954b5fe1..9ce1682ab7a3c 100644 --- a/testdata/default/cheats/Setup.t.sol +++ b/testdata/default/cheats/Setup.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract Victim { function assertSender(address sender) external { @@ -10,8 +9,7 @@ contract Victim { } } -contract VmSetupTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +contract VmSetupTest is Test { Victim victim; function setUp() public { diff --git a/testdata/default/cheats/Shuffle.t.sol b/testdata/default/cheats/Shuffle.t.sol index 565f596a6dcb5..5701fa7ab72c2 100644 --- a/testdata/default/cheats/Shuffle.t.sol +++ b/testdata/default/cheats/Shuffle.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract ShuffleTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract ShuffleTest is Test { function testDeterministicShuffle() public { // Use a known seed uint256 seed = 123456789; diff --git a/testdata/default/cheats/Sign.t.sol b/testdata/default/cheats/Sign.t.sol index b21a6050b76c1..ed0a9aa2e93de 100644 --- a/testdata/default/cheats/Sign.t.sol +++ b/testdata/default/cheats/Sign.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract SignTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract SignTest is Test { function testSignDigest(uint248 pk, bytes32 digest) public { vm.assume(pk != 0); diff --git a/testdata/default/cheats/SignP256.t.sol b/testdata/default/cheats/SignP256.t.sol index b92588ce9f823..d8d07acbf67b7 100644 --- a/testdata/default/cheats/SignP256.t.sol +++ b/testdata/default/cheats/SignP256.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract SignTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract SignTest is Test { function testSignP256() public { bytes32 pk = hex"A8568B74282DCC66FF70F10B4CE5CC7B391282F5381BBB4F4D8DD96974B16E6B"; bytes32 digest = hex"54705ba3baafdbdfba8c5f9a70f7a89bee98d906b53e31074da7baecdc0da9ad"; diff --git a/testdata/default/cheats/Skip.t.sol b/testdata/default/cheats/Skip.t.sol index d7e75fa0f51af..0eff55b95db30 100644 --- a/testdata/default/cheats/Skip.t.sol +++ b/testdata/default/cheats/Skip.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract SkipTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract SkipTest is Test { function testSkip() public { vm.skip(true); revert("Should not reach this revert"); diff --git a/testdata/default/cheats/Sleep.t.sol b/testdata/default/cheats/Sleep.t.sol index 7af548e742573..b3268d41d3672 100644 --- a/testdata/default/cheats/Sleep.t.sol +++ b/testdata/default/cheats/Sleep.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract SleepTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract SleepTest is Test { function testSleep() public { uint256 milliseconds = 1234; diff --git a/testdata/default/cheats/Sort.t.sol b/testdata/default/cheats/Sort.t.sol index 2f557d54c2bbc..91991b572a081 100644 --- a/testdata/default/cheats/Sort.t.sol +++ b/testdata/default/cheats/Sort.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract SortTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract SortTest is Test { function testSortCheatcode() public { uint256[] memory numbers = new uint256[](3); numbers[0] = 3; diff --git a/testdata/default/cheats/StateDiffBytesString.t.sol b/testdata/default/cheats/StateDiffBytesString.t.sol index 31d37e9bd5b74..a61e3ee37f60d 100644 --- a/testdata/default/cheats/StateDiffBytesString.t.sol +++ b/testdata/default/cheats/StateDiffBytesString.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract BytesStringStorage { // Short string (less than 32 bytes) @@ -48,8 +47,7 @@ contract BytesStringStorage { } } -contract StateDiffBytesStringTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +contract StateDiffBytesStringTest is Test { BytesStringStorage bytesStringStorage; function setUp() public { diff --git a/testdata/default/cheats/StateDiffMappings.t.sol b/testdata/default/cheats/StateDiffMappings.t.sol index b4ed985791cde..45b53e0dfc5f0 100644 --- a/testdata/default/cheats/StateDiffMappings.t.sol +++ b/testdata/default/cheats/StateDiffMappings.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract MappingStorage { // Simple mappings only @@ -29,8 +28,7 @@ contract MappingStorage { } } -contract StateDiffMappingsTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +contract StateDiffMappingsTest is Test { MappingStorage public mappingStorage; function setUp() public { diff --git a/testdata/default/cheats/StateDiffStorageLayout.t.sol b/testdata/default/cheats/StateDiffStorageLayout.t.sol index 027e3d8567098..298a8eb8bf236 100644 --- a/testdata/default/cheats/StateDiffStorageLayout.t.sol +++ b/testdata/default/cheats/StateDiffStorageLayout.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract SimpleStorage { uint256 public value; // Slot 0 @@ -97,8 +96,7 @@ contract TwoDArrayStorage { } } -contract StateDiffStorageLayoutTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +contract StateDiffStorageLayoutTest is Test { SimpleStorage simpleStorage; VariousArrays variousArrays; TwoDArrayStorage twoDArrayStorage; diff --git a/testdata/default/cheats/StateDiffStructTest.t.sol b/testdata/default/cheats/StateDiffStructTest.t.sol index a0b29f156c673..54e5403411dd4 100644 --- a/testdata/default/cheats/StateDiffStructTest.t.sol +++ b/testdata/default/cheats/StateDiffStructTest.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity 0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract DiffTest { // slot 0 @@ -49,8 +48,7 @@ contract DiffTest { } } -contract StateDiffStructTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +contract StateDiffStructTest is Test { DiffTest internal test; function setUp() public { diff --git a/testdata/default/cheats/StateSnapshots.t.sol b/testdata/default/cheats/StateSnapshots.t.sol index 8751a04094129..4a72639ce8c8d 100644 --- a/testdata/default/cheats/StateSnapshots.t.sol +++ b/testdata/default/cheats/StateSnapshots.t.sol @@ -1,17 +1,14 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; struct Storage { uint256 slot0; uint256 slot1; } -contract StateSnapshotTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract StateSnapshotTest is Test { Storage store; function setUp() public { @@ -105,9 +102,7 @@ contract StateSnapshotTest is DSTest { } // TODO: remove this test suite once `snapshot*` has been deprecated in favor of `snapshotState*`. -contract DeprecatedStateSnapshotTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract DeprecatedStateSnapshotTest is Test { Storage store; function setUp() public { diff --git a/testdata/default/cheats/StorageSlotState.t.sol b/testdata/default/cheats/StorageSlotState.t.sol index 7c2971f22a14f..6c80900038558 100644 --- a/testdata/default/cheats/StorageSlotState.t.sol +++ b/testdata/default/cheats/StorageSlotState.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract StorageSlotStateTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract StorageSlotStateTest is Test { function test_gas_two_reads() public { Read read = new Read(); read.number(); diff --git a/testdata/default/cheats/Store.t.sol b/testdata/default/cheats/Store.t.sol index 9a1ce6101c1b0..e096dc3f50341 100644 --- a/testdata/default/cheats/Store.t.sol +++ b/testdata/default/cheats/Store.t.sol @@ -1,16 +1,14 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract Storage { uint256 public slot0 = 10; uint256 public slot1 = 20; } -contract StoreTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +contract StoreTest is Test { Storage store; function setUp() public { diff --git a/testdata/default/cheats/StringUtils.t.sol b/testdata/default/cheats/StringUtils.t.sol index 256d65302a445..fbe8718d99cc6 100644 --- a/testdata/default/cheats/StringUtils.t.sol +++ b/testdata/default/cheats/StringUtils.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract StringManipulationTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract StringManipulationTest is Test { function testToLowercase() public { string memory original = "Hello World"; string memory lowercased = vm.toLowercase(original); diff --git a/testdata/default/cheats/ToString.t.sol b/testdata/default/cheats/ToString.t.sol index f19110e3e8655..3fda38c4e5f1b 100644 --- a/testdata/default/cheats/ToString.t.sol +++ b/testdata/default/cheats/ToString.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract ToStringTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract ToStringTest is Test { function testAddressToString() public { address testAddress = 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D; string memory stringAddress = vm.toString(testAddress); diff --git a/testdata/default/cheats/Toml.t.sol b/testdata/default/cheats/Toml.t.sol index 9802389877ed2..613ec7c4046fb 100644 --- a/testdata/default/cheats/Toml.t.sol +++ b/testdata/default/cheats/Toml.t.sol @@ -1,9 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; -import "../logs/console.sol"; +import "utils/Test.sol"; library TomlStructs { address constant HEVM_ADDRESS = address(bytes20(uint160(uint256(keccak256("hevm cheat code"))))); @@ -58,7 +56,7 @@ library TomlStructs { } } -contract ParseTomlTest is DSTest { +contract ParseTomlTest is Test { using TomlStructs for *; struct FlatToml { @@ -80,7 +78,6 @@ contract ParseTomlTest is DSTest { string name; } - Vm constant vm = Vm(HEVM_ADDRESS); string toml; function setUp() public { @@ -349,9 +346,7 @@ contract ParseTomlTest is DSTest { } } -contract WriteTomlTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract WriteTomlTest is Test { string json1; string json2; diff --git a/testdata/default/cheats/Travel.t.sol b/testdata/default/cheats/Travel.t.sol index b46d2e7ad7041..4937b679dc413 100644 --- a/testdata/default/cheats/Travel.t.sol +++ b/testdata/default/cheats/Travel.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract ChainIdTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract ChainIdTest is Test { function testChainId() public { vm.chainId(10); assertEq(block.chainid, 10, "chainId switch failed"); diff --git a/testdata/default/cheats/TryFfi.sol b/testdata/default/cheats/TryFfi.sol index 58d93a48b4fea..916377b6cc590 100644 --- a/testdata/default/cheats/TryFfi.sol +++ b/testdata/default/cheats/TryFfi.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity >=0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract TryFfiTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract TryFfiTest is Test { function testTryFfi() public { string[] memory inputs = new string[](3); inputs[0] = "bash"; diff --git a/testdata/default/cheats/UnixTime.t.sol b/testdata/default/cheats/UnixTime.t.sol index 29d86699f64d1..6d11cdb3da02f 100644 --- a/testdata/default/cheats/UnixTime.t.sol +++ b/testdata/default/cheats/UnixTime.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract UnixTimeTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract UnixTimeTest is Test { // This is really wide because CI sucks. uint256 constant errMargin = 1000; diff --git a/testdata/default/cheats/Wallet.t.sol b/testdata/default/cheats/Wallet.t.sol index d061b55ae45c5..e25ed4a9d071e 100644 --- a/testdata/default/cheats/Wallet.t.sol +++ b/testdata/default/cheats/Wallet.t.sol @@ -1,14 +1,11 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract Foo {} -contract WalletTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract WalletTest is Test { uint256 internal constant Q = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141; uint256 private constant UINT256_MAX = 115792089237316195423570985008687907853269984665640564039457584007913129639935; diff --git a/testdata/default/cheats/Warp.t.sol b/testdata/default/cheats/Warp.t.sol index 7ba53f6e5eda4..f3512944d6797 100644 --- a/testdata/default/cheats/Warp.t.sol +++ b/testdata/default/cheats/Warp.t.sol @@ -1,26 +1,23 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract WarpTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract WarpTest is Test { function testWarp() public { vm.warp(10); - assertEq(block.timestamp, 10, "warp failed"); + assertEq(vm.getBlockTimestamp(), 10, "warp failed"); } function testWarpFuzzed(uint32 jump) public { - uint256 pre = block.timestamp; - vm.warp(block.timestamp + jump); - assertEq(block.timestamp, pre + jump, "warp failed"); + uint256 pre = vm.getBlockTimestamp(); + vm.warp(vm.getBlockTimestamp() + jump); + assertEq(vm.getBlockTimestamp(), pre + jump, "warp failed"); } function testWarp2() public { - assertEq(block.timestamp, 1); + assertEq(vm.getBlockTimestamp(), 1); vm.warp(100); - assertEq(block.timestamp, 100); + assertEq(vm.getBlockTimestamp(), 100); } } diff --git a/testdata/default/cheats/dumpState.t.sol b/testdata/default/cheats/dumpState.t.sol index 8a8675ca5eace..887de131e5888 100644 --- a/testdata/default/cheats/dumpState.t.sol +++ b/testdata/default/cheats/dumpState.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract SimpleContract { constructor() { @@ -12,9 +11,7 @@ contract SimpleContract { } } -contract DumpStateTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract DumpStateTest is Test { function testDumpStateCheatAccount() public { // Path to temporary file that is deleted after the test string memory path = string.concat(vm.projectRoot(), "/fixtures/Json/test_dump_state_cheat.json"); diff --git a/testdata/default/cheats/getBlockNumber.t.sol b/testdata/default/cheats/getBlockNumber.t.sol index 18e2a163f3b86..491a726781b99 100644 --- a/testdata/default/cheats/getBlockNumber.t.sol +++ b/testdata/default/cheats/getBlockNumber.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract GetBlockNumberTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract GetBlockNumberTest is Test { function testGetBlockNumber() public { uint256 height = vm.getBlockNumber(); assertEq(height, uint256(block.number), "height should be equal to block.number"); diff --git a/testdata/default/cheats/loadAllocs.t.sol b/testdata/default/cheats/loadAllocs.t.sol index 94ce6804c1260..fa660e75fb775 100644 --- a/testdata/default/cheats/loadAllocs.t.sol +++ b/testdata/default/cheats/loadAllocs.t.sol @@ -1,11 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; -contract LoadAllocsTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +contract LoadAllocsTest is Test { address constant ALLOCD = address(0x420); address constant ALLOCD_B = address(0x421); diff --git a/testdata/default/core/BadSigAfterInvariant.t.sol b/testdata/default/core/BadSigAfterInvariant.t.sol index 7b485e24f4a04..1e2ce2f9a9448 100644 --- a/testdata/default/core/BadSigAfterInvariant.t.sol +++ b/testdata/default/core/BadSigAfterInvariant.t.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; +import "utils/Test.sol"; -contract BadSigAfterInvariant is DSTest { +contract BadSigAfterInvariant is Test { function afterinvariant() public {} function testShouldPassWithWarning() public { diff --git a/testdata/default/core/ContractEnvironment.t.sol b/testdata/default/core/ContractEnvironment.t.sol index 452fa88022557..ddb03b41a2556 100644 --- a/testdata/default/core/ContractEnvironment.t.sol +++ b/testdata/default/core/ContractEnvironment.t.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; +import "utils/Test.sol"; -contract ContractEnvironmentTest is DSTest { +contract ContractEnvironmentTest is Test { function chainId() internal view returns (uint256 id) { assembly { id := chainid() diff --git a/testdata/default/core/FailingTestAfterFailedSetup.t.sol b/testdata/default/core/FailingTestAfterFailedSetup.t.sol deleted file mode 100644 index c56f4ba5de605..0000000000000 --- a/testdata/default/core/FailingTestAfterFailedSetup.t.sol +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.18; - -import "ds-test/test.sol"; - -contract FailingTestAfterFailedSetupTest is DSTest { - function setUp() public { - assertTrue(false); - } - - function testAssertSuccess() public { - assertTrue(true); - } - - function testAssertFailure() public { - assertTrue(false); - } -} diff --git a/testdata/default/core/LegacyAssertions.t.sol b/testdata/default/core/LegacyAssertions.t.sol deleted file mode 100644 index c35a63417efc3..0000000000000 --- a/testdata/default/core/LegacyAssertions.t.sol +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.18; - -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract NoAssertionsRevertTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - - function testMultipleAssertFailures() public { - vm.assertEq(uint256(1), uint256(2)); - vm.assertLt(uint256(5), uint256(4)); - } -} - -contract LegacyAssertionsTest { - bool public failed; - - function testFlagNotSetSuccess() public {} - - function testFlagSetFailure() public { - failed = true; - } -} diff --git a/testdata/default/core/PaymentFailure.t.sol b/testdata/default/core/PaymentFailure.t.sol deleted file mode 100644 index 52c42fd376052..0000000000000 --- a/testdata/default/core/PaymentFailure.t.sol +++ /dev/null @@ -1,19 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.18; - -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract Payable { - function pay() public payable {} -} - -contract PaymentFailureTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - - function testCantPay() public { - Payable target = new Payable(); - vm.prank(address(1)); - target.pay{value: 1}(); - } -} diff --git a/testdata/default/core/Reverting.t.sol b/testdata/default/core/Reverting.t.sol index 73877cab0b542..699b2bf1123d3 100644 --- a/testdata/default/core/Reverting.t.sol +++ b/testdata/default/core/Reverting.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract RevertingTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract RevertingTest is Test { /// forge-config: default.allow_internal_expect_revert = true function testRevert() public { vm.expectRevert("should revert here"); diff --git a/testdata/default/core/SetupConsistency.t.sol b/testdata/default/core/SetupConsistency.t.sol index 08d766f0f9242..bf5a2e31935c1 100644 --- a/testdata/default/core/SetupConsistency.t.sol +++ b/testdata/default/core/SetupConsistency.t.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; +import "utils/Test.sol"; -contract SetupConsistencyCheck is DSTest { +contract SetupConsistencyCheck is Test { uint256 two; uint256 four; uint256 result; diff --git a/testdata/default/fork/ForkSame_1.t.sol b/testdata/default/fork/ForkSame_1.t.sol index 949c7ea9ec17d..f8c0234f5baa6 100644 --- a/testdata/default/fork/ForkSame_1.t.sol +++ b/testdata/default/fork/ForkSame_1.t.sol @@ -1,12 +1,10 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; -contract ForkTest is DSTest { +contract ForkTest is Test { address constant WETH_TOKEN_ADDR = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; - Vm constant vm = Vm(HEVM_ADDRESS); uint256 forkA; // this will create two _different_ forks during setup diff --git a/testdata/default/fork/ForkSame_2.t.sol b/testdata/default/fork/ForkSame_2.t.sol index 949c7ea9ec17d..f8c0234f5baa6 100644 --- a/testdata/default/fork/ForkSame_2.t.sol +++ b/testdata/default/fork/ForkSame_2.t.sol @@ -1,12 +1,10 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; -contract ForkTest is DSTest { +contract ForkTest is Test { address constant WETH_TOKEN_ADDR = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; - Vm constant vm = Vm(HEVM_ADDRESS); uint256 forkA; // this will create two _different_ forks during setup diff --git a/testdata/default/fork/LaunchFork.t.sol b/testdata/default/fork/LaunchFork.t.sol index 710ac97f51d97..8784b84b8e7e1 100644 --- a/testdata/default/fork/LaunchFork.t.sol +++ b/testdata/default/fork/LaunchFork.t.sol @@ -1,14 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.6.12; -import "ds-test/test.sol"; +import "utils/Test.sol"; import "./DssExecLib.sol"; -interface Vm { - function store(address account, bytes32 slot, bytes32 value) external; - function activeFork() external returns (uint256); -} - interface IWETH { function deposit() external payable; function balanceOf(address) external view returns (uint256); @@ -23,14 +18,13 @@ contract DummyContract { } } -contract ForkTest is DSTest { +abstract contract ForkTest is Test { address constant DAI_TOKEN_ADDR = 0x6B175474E89094C44Da98b954EedeAC495271d0F; address constant WETH_TOKEN_ADDR = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; // checks that we can retrieve the fork we launched with function testActiveFork() public { - Vm cheatvm = Vm(HEVM_ADDRESS); - uint256 activeFork = cheatvm.activeFork(); + uint256 activeFork = vm.activeFork(); // launch fork has id `0` assertEq(activeFork, 0); } @@ -52,13 +46,12 @@ contract ForkTest is DSTest { } function testCheatcode() public { - Vm cheatvm = Vm(HEVM_ADDRESS); IWETH WETH = IWETH(WETH_TOKEN_ADDR); 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; - cheatvm.store(WETH_TOKEN_ADDR, zero_address_balance_slot, value); + vm.store(WETH_TOKEN_ADDR, zero_address_balance_slot, value); assertEq( WETH.balanceOf(0x0000000000000000000000000000000000000000), 1, @@ -77,3 +70,9 @@ contract ForkTest is DSTest { assertEq(WETH.balanceOf(address(this)) - current, 1000, "WETH balance is not equal to deposited amount."); } } + +contract ForkTestHttp is ForkTest { + function setUp() public { + vm.createSelectFork("mainnet"); + } +} diff --git a/testdata/default/fs/Disabled.t.sol b/testdata/default/fs/Disabled.t.sol index 36f05c211fcad..19fb755c4f425 100644 --- a/testdata/default/fs/Disabled.t.sol +++ b/testdata/default/fs/Disabled.t.sol @@ -1,16 +1,19 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; -contract DisabledTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +// No permissions: all FS operations should revert. +/// forge-config: default.fs_permissions = [] +contract DisabledAccessTest is Test { function testReadFile() public { string memory path = "fixtures/File/read.txt"; vm._expectCheatcodeRevert(); vm.readFile(path); + + vm._expectCheatcodeRevert(); + vm.readFileBinary(path); } function testReadLine() public { @@ -20,21 +23,27 @@ contract DisabledTest is DSTest { } function testWriteFile() public { - string memory path = "fixtures/File/write_file.txt"; + string memory path = "fixtures/File/ignored/write_file.txt"; string memory data = "hello writable world"; + vm._expectCheatcodeRevert(); vm.writeFile(path, data); + + vm._expectCheatcodeRevert(); + vm.writeFileBinary(path, bytes(data)); } function testWriteLine() public { - string memory path = "fixtures/File/write_file.txt"; + string memory path = "fixtures/File/ignored/write_file.txt"; string memory data = "hello writable world"; + vm._expectCheatcodeRevert(); vm.writeLine(path, data); } function testRemoveFile() public { - string memory path = "fixtures/File/write_file.txt"; + string memory path = "fixtures/File/ignored/write_file.txt"; + vm._expectCheatcodeRevert(); vm.removeFile(path); } diff --git a/testdata/default/fs/Default.t.sol b/testdata/default/fs/ReadOnly.sol similarity index 68% rename from testdata/default/fs/Default.t.sol rename to testdata/default/fs/ReadOnly.sol index e1524963f6c3e..a738ae20e61c4 100644 --- a/testdata/default/fs/Default.t.sol +++ b/testdata/default/fs/ReadOnly.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; -contract DefaultAccessTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +// Default permissions: only read FS operations should succeed. +/// forge-config: default.fs_permissions = [{ access = "read", path = "./fixtures"}] +contract ReadOnlyAccessTest is Test { function testReadFile() public { string memory path = "fixtures/File/read.txt"; vm.readFile(path); @@ -20,7 +20,7 @@ contract DefaultAccessTest is DSTest { } function testWriteFile() public { - string memory path = "fixtures/File/write_file.txt"; + string memory path = "fixtures/File/ignored/write_file.txt"; string memory data = "hello writable world"; vm._expectCheatcodeRevert(); @@ -31,7 +31,7 @@ contract DefaultAccessTest is DSTest { } function testWriteLine() public { - string memory path = "fixtures/File/write_file.txt"; + string memory path = "fixtures/File/ignored/write_file.txt"; string memory data = "hello writable world"; vm._expectCheatcodeRevert(); @@ -39,7 +39,7 @@ contract DefaultAccessTest is DSTest { } function testRemoveFile() public { - string memory path = "fixtures/File/write_file.txt"; + string memory path = "fixtures/File/ignored/write_file.txt"; vm._expectCheatcodeRevert(); vm.removeFile(path); diff --git a/testdata/default/fuzz/Fuzz.t.sol b/testdata/default/fuzz/Fuzz.t.sol deleted file mode 100644 index b1cf54716be93..0000000000000 --- a/testdata/default/fuzz/Fuzz.t.sol +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.18; - -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract FuzzTest is DSTest { - constructor() { - emit log("constructor"); - } - - Vm constant vm = Vm(HEVM_ADDRESS); - - function setUp() public { - emit log("setUp"); - } - - function testShouldFailFuzz(uint8 x) public { - emit log("testFailFuzz"); - require(x > 128, "should revert"); - } - - function testSuccessfulFuzz(uint128 a, uint128 b) public { - emit log("testSuccessfulFuzz"); - assertEq(uint256(a) + uint256(b), uint256(a) + uint256(b)); - } - - function testToStringFuzz(bytes32 data) public { - vm.toString(data); - } -} diff --git a/testdata/default/fuzz/FuzzCollection.t.sol b/testdata/default/fuzz/FuzzCollection.t.sol deleted file mode 100644 index 0c98ddc66b6b2..0000000000000 --- a/testdata/default/fuzz/FuzzCollection.t.sol +++ /dev/null @@ -1,70 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.18; - -import "ds-test/test.sol"; - -contract SampleContract { - uint256 public counter; - uint256 public counterX2; - address public owner = address(0xBEEF); - bool public found_needle; - - event Incremented(uint256 counter); - - modifier onlyOwner() { - require(msg.sender == owner, "ONLY_OWNER"); - _; - } - - function compare(uint256 val) public { - if (val == 0x4446) { - found_needle = true; - } - } - - function incrementBy(uint256 numToIncrement) public onlyOwner { - counter += numToIncrement; - counterX2 += numToIncrement * 2; - - emit Incremented(counter); - } - - function breakTheInvariant(uint256 x) public { - if (x == 0x5556) { - counterX2 = 0; - } - } -} - -interface Vm { - function startPrank(address) external; - function expectRevert(bytes calldata msg) external; -} - -contract SampleContractTest is DSTest { - Vm hevm = Vm(HEVM_ADDRESS); - - event Incremented(uint256 counter); - - SampleContract public sample; - - function setUp() public { - sample = new SampleContract(); - } - - function testIncrement(address caller) public { - hevm.startPrank(address(caller)); - - hevm.expectRevert("ONLY_OWNER"); - sample.incrementBy(1); - } - - function testNeedle(uint256 needle) public { - sample.compare(needle); - require(!sample.found_needle(), "needle found."); - } - - function invariantCounter() public { - require(sample.counter() * 2 == sample.counterX2(), "broken counter."); - } -} diff --git a/testdata/default/fuzz/FuzzFailurePersist.t.sol b/testdata/default/fuzz/FuzzFailurePersist.t.sol deleted file mode 100644 index 3787060411e5d..0000000000000 --- a/testdata/default/fuzz/FuzzFailurePersist.t.sol +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.18; - -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -struct TestTuple { - address user; - uint256 amount; -} - -contract FuzzFailurePersistTest is DSTest { - Vm vm = Vm(HEVM_ADDRESS); - - function test_persist_fuzzed_failure( - uint256 x, - int256 y, - address addr, - bool cond, - string calldata test, - TestTuple calldata tuple, - address[] calldata addresses - ) public { - // dummy assume to trigger runs - vm.assume(x > 1 && x < 1111111111111111111111111111); - vm.assume(y > 1 && y < 1111111111111111111111111111); - require(false); - } -} diff --git a/testdata/default/fuzz/FuzzInt.t.sol b/testdata/default/fuzz/FuzzInt.t.sol deleted file mode 100644 index a47ff2953331f..0000000000000 --- a/testdata/default/fuzz/FuzzInt.t.sol +++ /dev/null @@ -1,58 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.18; - -import "ds-test/test.sol"; - -// https://github.com/foundry-rs/foundry/pull/735 behavior changed with https://github.com/foundry-rs/foundry/issues/3521 -// random values (instead edge cases) are generated if no fixtures defined -contract FuzzNumbersTest is DSTest { - function testPositive(int256) public { - assertTrue(true); - } - - function testNegativeHalf(int256 val) public { - assertTrue(val < 2 ** 128 - 1); - } - - function testNegative0(int256 val) public { - assertTrue(val == 0); - } - - function testNegative1(int256 val) public { - assertTrue(val == -1); - } - - function testNegative2(int128 val) public { - assertTrue(val == 1); - } - - function testNegativeMax0(int256 val) public { - assertTrue(val == type(int256).max); - } - - function testNegativeMax1(int256 val) public { - assertTrue(val == type(int256).max - 2); - } - - function testNegativeMin0(int256 val) public { - assertTrue(val == type(int256).min); - } - - function testNegativeMin1(int256 val) public { - assertTrue(val == type(int256).min + 2); - } - - function testEquality(int256 x, int256 y) public { - int256 xy; - - unchecked { - xy = x * y; - } - - if ((x != 0 && xy / x != y)) { - return; - } - - assertEq(((xy - 1) / 1e18) + 1, (xy - 1) / (1e18 + 1)); - } -} diff --git a/testdata/default/fuzz/FuzzPositive.t.sol b/testdata/default/fuzz/FuzzPositive.t.sol deleted file mode 100644 index 7d3639dfe5ec2..0000000000000 --- a/testdata/default/fuzz/FuzzPositive.t.sol +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.18; - -import "ds-test/test.sol"; - -contract FuzzPositive is DSTest { - function testSuccessChecker(uint256 val) public { - assertTrue(true); - } - - function testSuccessChecker2(int256 val) public { - assert(val == val); - } - - function testSuccessChecker3(uint32 val) public { - assert(val + 0 == val); - } -} diff --git a/testdata/default/fuzz/FuzzUint.t.sol b/testdata/default/fuzz/FuzzUint.t.sol deleted file mode 100644 index c0cbf6466c31b..0000000000000 --- a/testdata/default/fuzz/FuzzUint.t.sol +++ /dev/null @@ -1,46 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.18; - -import "ds-test/test.sol"; - -// https://github.com/foundry-rs/foundry/pull/735 behavior changed with https://github.com/foundry-rs/foundry/issues/3521 -// random values (instead edge cases) are generated if no fixtures defined -contract FuzzNumbersTest is DSTest { - function testPositive(uint256) public { - assertTrue(true); - } - - function testNegativeHalf(uint256 val) public { - assertTrue(val < 2 ** 128 - 1); - } - - function testNegative0(uint256 val) public { - assertTrue(val == 0); - } - - function testNegative2(uint256 val) public { - assertTrue(val == 2); - } - - function testNegative2Max(uint256 val) public { - assertTrue(val == type(uint256).max - 2); - } - - function testNegativeMax(uint256 val) public { - assertTrue(val == type(uint256).max); - } - - function testEquality(uint256 x, uint256 y) public { - uint256 xy; - - unchecked { - xy = x * y; - } - - if ((x != 0 && xy / x != y)) { - return; - } - - assertEq(((xy - 1) / 1e18) + 1, (xy - 1) / (1e18 + 1)); - } -} diff --git a/testdata/default/fuzz/invariant/common/InvariantAfterInvariant.t.sol b/testdata/default/fuzz/invariant/common/InvariantAfterInvariant.t.sol deleted file mode 100644 index 3030b43e077cc..0000000000000 --- a/testdata/default/fuzz/invariant/common/InvariantAfterInvariant.t.sol +++ /dev/null @@ -1,55 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.13; - -import "ds-test/test.sol"; - -struct FuzzSelector { - address addr; - bytes4[] selectors; -} - -contract AfterInvariantHandler { - uint256 public count; - - function inc() external { - count += 1; - } -} - -contract InvariantAfterInvariantTest is DSTest { - AfterInvariantHandler handler; - - function setUp() public { - handler = new AfterInvariantHandler(); - } - - function targetSelectors() public returns (FuzzSelector[] memory) { - FuzzSelector[] memory targets = new FuzzSelector[](1); - bytes4[] memory selectors = new bytes4[](1); - selectors[0] = handler.inc.selector; - targets[0] = FuzzSelector(address(handler), selectors); - return targets; - } - - function afterInvariant() public { - require(handler.count() < 10, "afterInvariant failure"); - } - - /// forge-config: default.invariant.runs = 1 - /// forge-config: default.invariant.depth = 11 - function invariant_after_invariant_failure() public view { - require(handler.count() < 20, "invariant after invariant failure"); - } - - /// forge-config: default.invariant.runs = 1 - /// forge-config: default.invariant.depth = 11 - function invariant_failure() public view { - require(handler.count() < 9, "invariant failure"); - } - - /// forge-config: default.invariant.runs = 1 - /// forge-config: default.invariant.depth = 5 - function invariant_success() public view { - require(handler.count() < 11, "invariant should not fail"); - } -} diff --git a/testdata/default/fuzz/invariant/common/InvariantAssume.t.sol b/testdata/default/fuzz/invariant/common/InvariantAssume.t.sol deleted file mode 100644 index 9808a870f7228..0000000000000 --- a/testdata/default/fuzz/invariant/common/InvariantAssume.t.sol +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.0; - -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract Handler is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - - function doSomething(uint256 param) public { - vm.assume(param == 0); - } -} - -contract InvariantAssume is DSTest { - Handler handler; - - function setUp() public { - handler = new Handler(); - } - - function invariant_dummy() public {} -} diff --git a/testdata/default/fuzz/invariant/common/InvariantCalldataDictionary.t.sol b/testdata/default/fuzz/invariant/common/InvariantCalldataDictionary.t.sol deleted file mode 100644 index 3d4c51eac41e5..0000000000000 --- a/testdata/default/fuzz/invariant/common/InvariantCalldataDictionary.t.sol +++ /dev/null @@ -1,95 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.18; - -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -struct FuzzSelector { - address addr; - bytes4[] selectors; -} - -// https://github.com/foundry-rs/foundry/issues/5868 -contract Owned { - address public owner; - address private ownerCandidate; - - constructor() { - owner = msg.sender; - } - - modifier onlyOwner() { - require(msg.sender == owner); - _; - } - - modifier onlyOwnerCandidate() { - require(msg.sender == ownerCandidate); - _; - } - - function transferOwnership(address candidate) external onlyOwner { - ownerCandidate = candidate; - } - - function acceptOwnership() external onlyOwnerCandidate { - owner = ownerCandidate; - } -} - -contract Handler is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - Owned owned; - - constructor(Owned _owned) { - owned = _owned; - } - - function transferOwnership(address sender, address candidate) external { - vm.assume(sender != address(0)); - vm.prank(sender); - owned.transferOwnership(candidate); - } - - function acceptOwnership(address sender) external { - vm.assume(sender != address(0)); - vm.prank(sender); - owned.acceptOwnership(); - } -} - -contract InvariantCalldataDictionary is DSTest { - address owner; - Owned owned; - Handler handler; - address[] actors; - - function setUp() public { - owner = address(this); - owned = new Owned(); - handler = new Handler(owned); - actors.push(owner); - actors.push(address(777)); - } - - function targetSelectors() public returns (FuzzSelector[] memory) { - FuzzSelector[] memory targets = new FuzzSelector[](1); - bytes4[] memory selectors = new bytes4[](2); - selectors[0] = handler.transferOwnership.selector; - selectors[1] = handler.acceptOwnership.selector; - targets[0] = FuzzSelector(address(handler), selectors); - return targets; - } - - function fixtureSender() external returns (address[] memory) { - return actors; - } - - function fixtureCandidate() external returns (address[] memory) { - return actors; - } - - function invariant_owner_never_changes() public { - assertEq(owned.owner(), owner); - } -} diff --git a/testdata/default/fuzz/invariant/common/InvariantCustomError.t.sol b/testdata/default/fuzz/invariant/common/InvariantCustomError.t.sol deleted file mode 100644 index 737cf5ba9dd05..0000000000000 --- a/testdata/default/fuzz/invariant/common/InvariantCustomError.t.sol +++ /dev/null @@ -1,35 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.0; - -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract ContractWithCustomError { - error InvariantCustomError(uint256, string); - - function revertWithInvariantCustomError() external { - revert InvariantCustomError(111, "custom"); - } -} - -contract Handler is DSTest { - ContractWithCustomError target; - - constructor() { - target = new ContractWithCustomError(); - } - - function revertTarget() external { - target.revertWithInvariantCustomError(); - } -} - -contract InvariantCustomError is DSTest { - Handler handler; - - function setUp() external { - handler = new Handler(); - } - - function invariant_decode_error() public {} -} diff --git a/testdata/default/fuzz/invariant/common/InvariantExcludedSenders.t.sol b/testdata/default/fuzz/invariant/common/InvariantExcludedSenders.t.sol deleted file mode 100644 index 8fe0bed2c6e7c..0000000000000 --- a/testdata/default/fuzz/invariant/common/InvariantExcludedSenders.t.sol +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.13; - -import "ds-test/test.sol"; - -contract InvariantSenders { - function checkSender() external { - require(msg.sender != 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D, "sender cannot be cheatcode address"); - require(msg.sender != 0x000000000000000000636F6e736F6c652e6c6f67, "sender cannot be console address"); - require(msg.sender != 0x4e59b44847b379578588920cA78FbF26c0B4956C, "sender cannot be CREATE2 deployer"); - } -} - -contract InvariantExcludedSendersTest is DSTest { - InvariantSenders target; - - function setUp() public { - target = new InvariantSenders(); - } - - function invariant_check_sender() public view {} -} diff --git a/testdata/default/fuzz/invariant/common/InvariantFixtures.t.sol b/testdata/default/fuzz/invariant/common/InvariantFixtures.t.sol deleted file mode 100644 index b3f1e17cb2497..0000000000000 --- a/testdata/default/fuzz/invariant/common/InvariantFixtures.t.sol +++ /dev/null @@ -1,77 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.0; - -import "ds-test/test.sol"; - -contract Target { - bool ownerFound; - bool amountFound; - bool magicFound; - bool keyFound; - bool backupFound; - bool extraStringFound; - - function fuzzWithFixtures( - address owner_, - uint256 _amount, - int32 magic, - bytes32 key, - bytes memory backup, - string memory extra - ) external { - if (owner_ == address(0x6B175474E89094C44Da98b954EedeAC495271d0F)) { - ownerFound = true; - } - if (_amount == 1122334455) amountFound = true; - if (magic == -777) magicFound = true; - if (key == "abcd1234") keyFound = true; - if (keccak256(backup) == keccak256("qwerty1234")) backupFound = true; - if (keccak256(abi.encodePacked(extra)) == keccak256(abi.encodePacked("112233aabbccdd"))) { - extraStringFound = true; - } - } - - function isCompromised() public view returns (bool) { - return ownerFound && amountFound && magicFound && keyFound && backupFound && extraStringFound; - } -} - -/// Try to compromise target contract by finding all accepted values using fixtures. -contract InvariantFixtures is DSTest { - Target target; - address[] public fixture_owner_ = [address(0x6B175474E89094C44Da98b954EedeAC495271d0F)]; - uint256[] public fixture_amount = [1, 2, 1122334455]; - - function setUp() public { - target = new Target(); - } - - function fixtureMagic() external returns (int32[2] memory) { - int32[2] memory magic; - magic[0] = -777; - magic[1] = 777; - return magic; - } - - function fixtureKey() external pure returns (bytes32[] memory) { - bytes32[] memory keyFixture = new bytes32[](1); - keyFixture[0] = "abcd1234"; - return keyFixture; - } - - function fixtureBackup() external pure returns (bytes[] memory) { - bytes[] memory backupFixture = new bytes[](1); - backupFixture[0] = "qwerty1234"; - return backupFixture; - } - - function fixtureExtra() external pure returns (string[] memory) { - string[] memory extraFixture = new string[](1); - extraFixture[0] = "112233aabbccdd"; - return extraFixture; - } - - function invariant_target_not_compromised() public { - assertEq(target.isCompromised(), false); - } -} diff --git a/testdata/default/fuzz/invariant/common/InvariantHandlerFailure.t.sol b/testdata/default/fuzz/invariant/common/InvariantHandlerFailure.t.sol deleted file mode 100644 index 5ff50e782ac55..0000000000000 --- a/testdata/default/fuzz/invariant/common/InvariantHandlerFailure.t.sol +++ /dev/null @@ -1,35 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.0; - -import "ds-test/test.sol"; - -struct FuzzSelector { - address addr; - bytes4[] selectors; -} - -contract Handler is DSTest { - function doSomething() public { - require(false, "failed on revert"); - } -} - -contract InvariantHandlerFailure is DSTest { - bytes4[] internal selectors; - - Handler handler; - - function targetSelectors() public returns (FuzzSelector[] memory) { - FuzzSelector[] memory targets = new FuzzSelector[](1); - bytes4[] memory selectors = new bytes4[](1); - selectors[0] = handler.doSomething.selector; - targets[0] = FuzzSelector(address(handler), selectors); - return targets; - } - - function setUp() public { - handler = new Handler(); - } - - function statefulFuzz_BrokenInvariant() public {} -} diff --git a/testdata/default/fuzz/invariant/common/InvariantInnerContract.t.sol b/testdata/default/fuzz/invariant/common/InvariantInnerContract.t.sol deleted file mode 100644 index 817e65d179f81..0000000000000 --- a/testdata/default/fuzz/invariant/common/InvariantInnerContract.t.sol +++ /dev/null @@ -1,50 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.18; - -import "ds-test/test.sol"; - -/*////////////////////////////////////////////////////////////// - Here we test that the fuzz engine can include a contract created during the fuzz - in its fuzz dictionary and eventually break the invariant. - Specifically, can Judas, a created contract from Jesus, break Jesus contract - by revealing his identity. -/*/ -///////////////////////////////////////////////////////////// - -contract Jesus { - address fren; - bool public identity_revealed; - - function create_fren() public { - fren = address(new Judas()); - } - - function kiss() public { - require(msg.sender == fren); - identity_revealed = true; - } -} - -contract Judas { - Jesus jesus; - - constructor() { - jesus = Jesus(msg.sender); - } - - function betray() public { - jesus.kiss(); - } -} - -contract InvariantInnerContract is DSTest { - Jesus jesus; - - function setUp() public { - jesus = new Jesus(); - } - - function invariantHideJesus() public { - require(jesus.identity_revealed() == false, "jesus betrayed"); - } -} diff --git a/testdata/default/fuzz/invariant/common/InvariantPreserveState.t.sol b/testdata/default/fuzz/invariant/common/InvariantPreserveState.t.sol deleted file mode 100644 index bd70dd3aeafba..0000000000000 --- a/testdata/default/fuzz/invariant/common/InvariantPreserveState.t.sol +++ /dev/null @@ -1,49 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.18; - -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -struct FuzzSelector { - address addr; - bytes4[] selectors; -} - -// https://github.com/foundry-rs/foundry/issues/7219 - -contract Handler is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - - function thisFunctionReverts() external { - if (block.number < 10) {} else { - revert(); - } - } - - function advanceTime(uint256 blocks) external { - blocks = blocks % 10; - vm.roll(block.number + blocks); - vm.warp(block.timestamp + blocks * 12); - } -} - -contract InvariantPreserveState is DSTest { - Handler handler; - - function setUp() public { - handler = new Handler(); - } - - function targetSelectors() public returns (FuzzSelector[] memory) { - FuzzSelector[] memory targets = new FuzzSelector[](1); - bytes4[] memory selectors = new bytes4[](2); - selectors[0] = handler.thisFunctionReverts.selector; - selectors[1] = handler.advanceTime.selector; - targets[0] = FuzzSelector(address(handler), selectors); - return targets; - } - - function invariant_preserve_state() public { - assertTrue(true); - } -} diff --git a/testdata/default/fuzz/invariant/common/InvariantReentrancy.t.sol b/testdata/default/fuzz/invariant/common/InvariantReentrancy.t.sol deleted file mode 100644 index 74a01f1805de6..0000000000000 --- a/testdata/default/fuzz/invariant/common/InvariantReentrancy.t.sol +++ /dev/null @@ -1,55 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.18; - -import "ds-test/test.sol"; - -contract Malicious { - function world() public { - // add code so contract is accounted as valid sender - // see https://github.com/foundry-rs/foundry/issues/4245 - payable(msg.sender).call(""); - } -} - -contract Vulnerable { - bool public open_door = false; - bool public stolen = false; - Malicious mal; - - constructor(address _mal) { - mal = Malicious(_mal); - } - - function hello() public { - open_door = true; - mal.world(); - open_door = false; - } - - function backdoor() public { - require(open_door, ""); - stolen = true; - } -} - -contract InvariantReentrancy is DSTest { - Vulnerable vuln; - Malicious mal; - - function setUp() public { - mal = new Malicious(); - vuln = new Vulnerable(address(mal)); - } - - // do not include `mal` in identified contracts - // see https://github.com/foundry-rs/foundry/issues/4245 - function targetContracts() public view returns (address[] memory) { - address[] memory targets = new address[](1); - targets[0] = address(vuln); - return targets; - } - - function invariantNotStolen() public { - require(vuln.stolen() == false, "stolen"); - } -} diff --git a/testdata/default/fuzz/invariant/common/InvariantRollFork.t.sol b/testdata/default/fuzz/invariant/common/InvariantRollFork.t.sol deleted file mode 100644 index d15619b635f18..0000000000000 --- a/testdata/default/fuzz/invariant/common/InvariantRollFork.t.sol +++ /dev/null @@ -1,50 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.13; - -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -interface IERC20 { - function totalSupply() external view returns (uint256 supply); -} - -contract RollForkHandler is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - uint256 public totalSupply; - - function work() external { - vm.rollFork(block.number + 1); - totalSupply = IERC20(0x6B175474E89094C44Da98b954EedeAC495271d0F).totalSupply(); - } -} - -contract InvariantRollForkBlockTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - RollForkHandler forkHandler; - - function setUp() public { - vm.createSelectFork("mainnet", 19812632); - forkHandler = new RollForkHandler(); - } - - /// forge-config: default.invariant.runs = 2 - /// forge-config: default.invariant.depth = 4 - function invariant_fork_handler_block() public { - require(block.number < 19812634, "too many blocks mined"); - } -} - -contract InvariantRollForkStateTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - RollForkHandler forkHandler; - - function setUp() public { - vm.createSelectFork("mainnet", 19812632); - forkHandler = new RollForkHandler(); - } - - /// forge-config: default.invariant.runs = 1 - function invariant_fork_handler_state() public { - require(forkHandler.totalSupply() < 3254378807384273078310283461, "wrong supply"); - } -} diff --git a/testdata/default/fuzz/invariant/common/InvariantScrapeValues.t.sol b/testdata/default/fuzz/invariant/common/InvariantScrapeValues.t.sol deleted file mode 100644 index 40824a2602e77..0000000000000 --- a/testdata/default/fuzz/invariant/common/InvariantScrapeValues.t.sol +++ /dev/null @@ -1,69 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.13; - -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract FindFromReturnValue { - bool public found = false; - - function seed() public returns (int256) { - int256 mystery = 13337; - return (1337 + mystery); - } - - function find(int256 i) public { - int256 mystery = 13337; - if (i == 1337 + mystery) { - found = true; - } - } -} - -contract FindFromReturnValueTest is DSTest { - FindFromReturnValue target; - - function setUp() public { - target = new FindFromReturnValue(); - } - - /// forge-config: default.invariant.runs = 50 - /// forge-config: default.invariant.depth = 300 - /// forge-config: default.invariant.fail-on-revert = true - function invariant_value_not_found() public view { - require(!target.found(), "value from return found"); - } -} - -contract FindFromLogValue { - event FindFromLog(int256 indexed mystery, bytes32 rand); - - bool public found = false; - - function seed() public { - int256 mystery = 13337; - emit FindFromLog(1337 + mystery, keccak256(abi.encodePacked("mystery"))); - } - - function find(int256 i) public { - int256 mystery = 13337; - if (i == 1337 + mystery) { - found = true; - } - } -} - -contract FindFromLogValueTest is DSTest { - FindFromLogValue target; - - function setUp() public { - target = new FindFromLogValue(); - } - - /// forge-config: default.invariant.runs = 50 - /// forge-config: default.invariant.depth = 300 - /// forge-config: default.invariant.fail-on-revert = true - function invariant_value_not_found() public view { - require(!target.found(), "value from logs found"); - } -} diff --git a/testdata/default/fuzz/invariant/common/InvariantSequenceNoReverts.t.sol b/testdata/default/fuzz/invariant/common/InvariantSequenceNoReverts.t.sol deleted file mode 100644 index 993d806f81b38..0000000000000 --- a/testdata/default/fuzz/invariant/common/InvariantSequenceNoReverts.t.sol +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.13; - -import "ds-test/test.sol"; - -contract SequenceNoReverts { - uint256 public count; - - function work(uint256 x) public { - require(x % 2 != 0); - count++; - } -} - -contract SequenceNoRevertsTest is DSTest { - SequenceNoReverts target; - - function setUp() public { - target = new SequenceNoReverts(); - } - - function invariant_no_reverts() public view { - require(target.count() < 10, "condition met"); - } -} diff --git a/testdata/default/fuzz/invariant/common/InvariantShrinkBigSequence.t.sol b/testdata/default/fuzz/invariant/common/InvariantShrinkBigSequence.t.sol deleted file mode 100644 index 5699d9c455e89..0000000000000 --- a/testdata/default/fuzz/invariant/common/InvariantShrinkBigSequence.t.sol +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.13; - -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract ShrinkBigSequence { - uint256 cond; - - function work(uint256 x) public { - if (x % 2 != 0 && x < 9000) { - cond++; - } - } - - function checkCond() public view { - require(cond < 77, "condition met"); - } -} - -contract ShrinkBigSequenceTest is DSTest { - ShrinkBigSequence target; - - function setUp() public { - target = new ShrinkBigSequence(); - } - - function invariant_shrink_big_sequence() public view { - target.checkCond(); - } -} diff --git a/testdata/default/fuzz/invariant/common/InvariantShrinkFailOnRevert.t.sol b/testdata/default/fuzz/invariant/common/InvariantShrinkFailOnRevert.t.sol deleted file mode 100644 index d971367b69988..0000000000000 --- a/testdata/default/fuzz/invariant/common/InvariantShrinkFailOnRevert.t.sol +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.13; - -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract ShrinkFailOnRevert { - uint256 cond; - - function work(uint256 x) public { - if (x % 2 != 0 && x < 9000) { - cond++; - } - require(cond < 10, "condition met"); - } -} - -contract ShrinkFailOnRevertTest is DSTest { - ShrinkFailOnRevert target; - - function setUp() public { - target = new ShrinkFailOnRevert(); - } - - function invariant_shrink_fail_on_revert() public view {} -} diff --git a/testdata/default/fuzz/invariant/common/InvariantShrinkWithAssert.t.sol b/testdata/default/fuzz/invariant/common/InvariantShrinkWithAssert.t.sol deleted file mode 100644 index fa4a6e945804e..0000000000000 --- a/testdata/default/fuzz/invariant/common/InvariantShrinkWithAssert.t.sol +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.13; - -import "ds-test/test.sol"; - -contract Counter { - uint256 public number; - - function increment() public { - number++; - } - - function decrement() public { - number--; - } -} - -contract InvariantShrinkWithAssert is DSTest { - Counter public counter; - - function setUp() public { - counter = new Counter(); - } - - function invariant_with_assert() public { - assertTrue(counter.number() < 2, "wrong counter"); - } - - function invariant_with_require() public { - require(counter.number() < 2, "wrong counter"); - } -} diff --git a/testdata/default/fuzz/invariant/common/InvariantTest1.t.sol b/testdata/default/fuzz/invariant/common/InvariantTest1.t.sol deleted file mode 100644 index bb62f34c6a965..0000000000000 --- a/testdata/default/fuzz/invariant/common/InvariantTest1.t.sol +++ /dev/null @@ -1,39 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.18; - -import "ds-test/test.sol"; - -contract InvariantBreaker { - bool public flag0 = true; - bool public flag1 = true; - - function set0(int256 val) public returns (bool) { - if (val % 100 == 0) { - flag0 = false; - } - return flag0; - } - - function set1(int256 val) public returns (bool) { - if (val % 10 == 0 && !flag0) { - flag1 = false; - } - return flag1; - } -} - -contract InvariantTest is DSTest { - InvariantBreaker inv; - - function setUp() public { - inv = new InvariantBreaker(); - } - - function invariant_neverFalse() public { - require(inv.flag1(), "false"); - } - - function statefulFuzz_neverFalseWithInvariantAlias() public { - require(inv.flag1(), "false"); - } -} diff --git a/testdata/default/fuzz/invariant/target/ExcludeContracts.t.sol b/testdata/default/fuzz/invariant/target/ExcludeContracts.t.sol deleted file mode 100644 index e2e850e316d1e..0000000000000 --- a/testdata/default/fuzz/invariant/target/ExcludeContracts.t.sol +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.18; - -import "ds-test/test.sol"; - -contract Hello { - bool public world = true; - - function change() public { - world = false; - } -} - -contract ExcludeContracts is DSTest { - Hello hello; - - function setUp() public { - hello = new Hello(); - new Hello(); - } - - function excludeContracts() public returns (address[] memory) { - address[] memory addrs = new address[](1); - addrs[0] = address(hello); - return addrs; - } - - function invariantTrueWorld() public { - require(hello.world() == true, "false world"); - } -} diff --git a/testdata/default/fuzz/invariant/target/ExcludeSelectors.t.sol b/testdata/default/fuzz/invariant/target/ExcludeSelectors.t.sol deleted file mode 100644 index e2251f42c8126..0000000000000 --- a/testdata/default/fuzz/invariant/target/ExcludeSelectors.t.sol +++ /dev/null @@ -1,41 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.18; - -import "ds-test/test.sol"; - -struct FuzzSelector { - address addr; - bytes4[] selectors; -} - -contract Hello { - bool public world = false; - - function change() public { - world = true; - } - - function real_change() public { - world = false; - } -} - -contract ExcludeSelectors is DSTest { - Hello hello; - - function setUp() public { - hello = new Hello(); - } - - function excludeSelectors() public returns (FuzzSelector[] memory) { - FuzzSelector[] memory targets = new FuzzSelector[](1); - bytes4[] memory selectors = new bytes4[](1); - selectors[0] = Hello.change.selector; - targets[0] = FuzzSelector(address(hello), selectors); - return targets; - } - - function invariantFalseWorld() public { - require(hello.world() == false, "true world"); - } -} diff --git a/testdata/default/fuzz/invariant/target/ExcludeSenders.t.sol b/testdata/default/fuzz/invariant/target/ExcludeSenders.t.sol deleted file mode 100644 index dda07074d18c7..0000000000000 --- a/testdata/default/fuzz/invariant/target/ExcludeSenders.t.sol +++ /dev/null @@ -1,45 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.18; - -import "ds-test/test.sol"; - -contract Hello { - address seed_address = address(0xdeadbeef); - bool public world = true; - - function changeBeef() public { - require(msg.sender == address(0xdeadbeef)); - world = false; - } - - // address(0) should be automatically excluded - function change0() public { - require(msg.sender == address(0)); - world = false; - } -} - -contract ExcludeSenders is DSTest { - Hello hello; - - function setUp() public { - hello = new Hello(); - } - - function excludeSenders() public returns (address[] memory) { - address[] memory addrs = new address[](1); - addrs[0] = address(0xdeadbeef); - return addrs; - } - - // Tests clashing. Exclusion takes priority. - function targetSenders() public returns (address[] memory) { - address[] memory addrs = new address[](1); - addrs[0] = address(0xdeadbeef); - return addrs; - } - - function invariantTrueWorld() public { - require(hello.world() == true, "false world"); - } -} diff --git a/testdata/default/fuzz/invariant/target/FuzzedTargetContracts.t.sol b/testdata/default/fuzz/invariant/target/FuzzedTargetContracts.t.sol deleted file mode 100644 index 759810611e95b..0000000000000 --- a/testdata/default/fuzz/invariant/target/FuzzedTargetContracts.t.sol +++ /dev/null @@ -1,66 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.18; - -import "ds-test/test.sol"; - -interface Vm { - function etch(address target, bytes calldata newRuntimeBytecode) external; -} - -// https://github.com/foundry-rs/foundry/issues/5625 -// https://github.com/foundry-rs/foundry/issues/6166 -// `Target.wrongSelector` is not called when handler added as `targetContract` -// `Target.wrongSelector` is called (and test fails) when no `targetContract` set -contract Target { - uint256 count; - - function wrongSelector() external { - revert("wrong target selector called"); - } - - function goodSelector() external { - count++; - } -} - -contract Handler is DSTest { - function increment() public { - Target(0x6B175474E89094C44Da98b954EedeAC495271d0F).goodSelector(); - } -} - -contract ExplicitTargetContract is DSTest { - Vm vm = Vm(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D); - Handler handler; - - function setUp() public { - Target target = new Target(); - bytes memory targetCode = address(target).code; - vm.etch(address(0x6B175474E89094C44Da98b954EedeAC495271d0F), targetCode); - - handler = new Handler(); - } - - function targetContracts() public returns (address[] memory) { - address[] memory addrs = new address[](1); - addrs[0] = address(handler); - return addrs; - } - - function invariant_explicit_target() public {} -} - -contract DynamicTargetContract is DSTest { - Vm vm = Vm(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D); - Handler handler; - - function setUp() public { - Target target = new Target(); - bytes memory targetCode = address(target).code; - vm.etch(address(0x6B175474E89094C44Da98b954EedeAC495271d0F), targetCode); - - handler = new Handler(); - } - - function invariant_dynamic_targets() public {} -} diff --git a/testdata/default/fuzz/invariant/target/TargetContracts.t.sol b/testdata/default/fuzz/invariant/target/TargetContracts.t.sol deleted file mode 100644 index d24c7eb5282a4..0000000000000 --- a/testdata/default/fuzz/invariant/target/TargetContracts.t.sol +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.18; - -import "ds-test/test.sol"; - -contract Hello { - bool public world = true; - - function change() public { - world = false; - } -} - -contract TargetContracts is DSTest { - Hello hello1; - Hello hello2; - - function setUp() public { - hello1 = new Hello(); - hello2 = new Hello(); - } - - function targetContracts() public returns (address[] memory) { - address[] memory addrs = new address[](1); - addrs[0] = address(hello1); - return addrs; - } - - function invariantTrueWorld() public { - require(hello2.world() == true, "false world"); - } -} diff --git a/testdata/default/fuzz/invariant/target/TargetInterfaces.t.sol b/testdata/default/fuzz/invariant/target/TargetInterfaces.t.sol deleted file mode 100644 index 30b4a05e3eaf9..0000000000000 --- a/testdata/default/fuzz/invariant/target/TargetInterfaces.t.sol +++ /dev/null @@ -1,72 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.18; - -import "ds-test/test.sol"; - -struct FuzzInterface { - address target; - string[] artifacts; -} - -contract Hello { - bool public world; - - function changeWorld() external { - world = true; - } -} - -interface IHello { - function world() external view returns (bool); - function changeWorld() external; -} - -contract HelloProxy { - address internal immutable _implementation; - - constructor(address implementation_) { - _implementation = implementation_; - } - - function _delegate(address implementation) internal { - assembly { - calldatacopy(0, 0, calldatasize()) - - let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0) - - returndatacopy(0, 0, returndatasize()) - - switch result - case 0 { revert(0, returndatasize()) } - default { return(0, returndatasize()) } - } - } - - fallback() external payable { - _delegate(_implementation); - } -} - -contract TargetWorldInterfaces is DSTest { - IHello proxy; - - function setUp() public { - Hello hello = new Hello(); - proxy = IHello(address(new HelloProxy(address(hello)))); - } - - function targetInterfaces() public returns (FuzzInterface[] memory) { - FuzzInterface[] memory targets = new FuzzInterface[](1); - - string[] memory artifacts = new string[](1); - artifacts[0] = "IHello"; - - targets[0] = FuzzInterface(address(proxy), artifacts); - - return targets; - } - - function invariantTrueWorld() public { - require(proxy.world() == false, "false world"); - } -} diff --git a/testdata/default/fuzz/invariant/target/TargetSelectors.t.sol b/testdata/default/fuzz/invariant/target/TargetSelectors.t.sol deleted file mode 100644 index c74ac7fa18114..0000000000000 --- a/testdata/default/fuzz/invariant/target/TargetSelectors.t.sol +++ /dev/null @@ -1,41 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.18; - -import "ds-test/test.sol"; - -struct FuzzSelector { - address addr; - bytes4[] selectors; -} - -contract Hello { - bool public world = true; - - function change() public { - world = true; - } - - function real_change() public { - world = false; - } -} - -contract TargetSelectors is DSTest { - Hello hello; - - function setUp() public { - hello = new Hello(); - } - - function targetSelectors() public returns (FuzzSelector[] memory) { - FuzzSelector[] memory targets = new FuzzSelector[](1); - bytes4[] memory selectors = new bytes4[](1); - selectors[0] = Hello.change.selector; - targets[0] = FuzzSelector(address(hello), selectors); - return targets; - } - - function invariantTrueWorld() public { - require(hello.world() == true, "false world"); - } -} diff --git a/testdata/default/fuzz/invariant/target/TargetSenders.t.sol b/testdata/default/fuzz/invariant/target/TargetSenders.t.sol deleted file mode 100644 index 6fa4c9a6387d5..0000000000000 --- a/testdata/default/fuzz/invariant/target/TargetSenders.t.sol +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.18; - -import "ds-test/test.sol"; - -contract Hello { - bool public world = true; - - function change() public { - require(msg.sender == address(0xdeadbeef)); - world = false; - } -} - -contract TargetSenders is DSTest { - Hello hello; - - function setUp() public { - hello = new Hello(); - } - - function targetSenders() public returns (address[] memory) { - address[] memory addrs = new address[](1); - addrs[0] = address(0xdeadbeef); - return addrs; - } - - function invariantTrueWorld() public { - require(hello.world() == true, "false world"); - } -} diff --git a/testdata/default/fuzz/invariant/targetAbi/ExcludeArtifacts.t.sol b/testdata/default/fuzz/invariant/targetAbi/ExcludeArtifacts.t.sol deleted file mode 100644 index 86ca6d5439b7a..0000000000000 --- a/testdata/default/fuzz/invariant/targetAbi/ExcludeArtifacts.t.sol +++ /dev/null @@ -1,45 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.18; - -import "ds-test/test.sol"; - -// Will get automatically excluded. Otherwise it would throw error. -contract NoMutFunctions { - function no_change() public pure {} -} - -contract Excluded { - bool public world = true; - - function change() public { - world = false; - } -} - -contract Hello { - bool public world = true; - - function change() public { - world = false; - } -} - -contract ExcludeArtifacts is DSTest { - Excluded excluded; - - function setUp() public { - excluded = new Excluded(); - new Hello(); - new NoMutFunctions(); - } - - function excludeArtifacts() public returns (string[] memory) { - string[] memory abis = new string[](1); - abis[0] = "default/fuzz/invariant/targetAbi/ExcludeArtifacts.t.sol:Excluded"; - return abis; - } - - function invariantShouldPass() public { - require(excluded.world() == true, "false world"); - } -} diff --git a/testdata/default/fuzz/invariant/targetAbi/TargetArtifactSelectors.t.sol b/testdata/default/fuzz/invariant/targetAbi/TargetArtifactSelectors.t.sol deleted file mode 100644 index a8d9c2799486d..0000000000000 --- a/testdata/default/fuzz/invariant/targetAbi/TargetArtifactSelectors.t.sol +++ /dev/null @@ -1,42 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.18; - -import "ds-test/test.sol"; - -struct FuzzArtifactSelector { - string artifact; - bytes4[] selectors; -} - -contract Hi { - bool public world = true; - - function no_change() public { - world = true; - } - - function change() public { - world = false; - } -} - -contract TargetArtifactSelectors is DSTest { - Hi hello; - - function setUp() public { - hello = new Hi(); - } - - function targetArtifactSelectors() public returns (FuzzArtifactSelector[] memory) { - FuzzArtifactSelector[] memory targets = new FuzzArtifactSelector[](1); - bytes4[] memory selectors = new bytes4[](1); - selectors[0] = Hi.no_change.selector; - targets[0] = - FuzzArtifactSelector("default/fuzz/invariant/targetAbi/TargetArtifactSelectors.t.sol:Hi", selectors); - return targets; - } - - function invariantShouldPass() public { - require(hello.world() == true, "false world"); - } -} diff --git a/testdata/default/fuzz/invariant/targetAbi/TargetArtifactSelectors2.t.sol b/testdata/default/fuzz/invariant/targetAbi/TargetArtifactSelectors2.t.sol deleted file mode 100644 index 162d9cc2e1106..0000000000000 --- a/testdata/default/fuzz/invariant/targetAbi/TargetArtifactSelectors2.t.sol +++ /dev/null @@ -1,72 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.18; - -import "ds-test/test.sol"; - -struct FuzzArtifactSelector { - string artifact; - bytes4[] selectors; -} - -contract Parent { - bool public should_be_true = true; - address public child; - - function change() public { - child = msg.sender; - should_be_true = false; - } - - function create() public { - new Child(); - } -} - -contract Child { - Parent parent; - bool public changed = false; - - constructor() { - parent = Parent(msg.sender); - } - - function change_parent() public { - parent.change(); - } - - function tracked_change_parent() public { - parent.change(); - } -} - -contract TargetArtifactSelectors2 is DSTest { - Parent parent; - - function setUp() public { - parent = new Parent(); - } - - function targetArtifactSelectors() public returns (FuzzArtifactSelector[] memory) { - FuzzArtifactSelector[] memory targets = new FuzzArtifactSelector[](2); - bytes4[] memory selectors_child = new bytes4[](1); - - selectors_child[0] = Child.change_parent.selector; - targets[0] = FuzzArtifactSelector( - "default/fuzz/invariant/targetAbi/TargetArtifactSelectors2.t.sol:Child", selectors_child - ); - - bytes4[] memory selectors_parent = new bytes4[](1); - selectors_parent[0] = Parent.create.selector; - targets[1] = FuzzArtifactSelector( - "default/fuzz/invariant/targetAbi/TargetArtifactSelectors2.t.sol:Parent", selectors_parent - ); - return targets; - } - - function invariantShouldFail() public { - if (!parent.should_be_true()) { - require(!Child(address(parent.child())).changed(), "should have not happened"); - } - require(parent.should_be_true() == true, "it's false"); - } -} diff --git a/testdata/default/fuzz/invariant/targetAbi/TargetArtifacts.t.sol b/testdata/default/fuzz/invariant/targetAbi/TargetArtifacts.t.sol deleted file mode 100644 index 28fa146059f92..0000000000000 --- a/testdata/default/fuzz/invariant/targetAbi/TargetArtifacts.t.sol +++ /dev/null @@ -1,44 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.18; - -import "ds-test/test.sol"; - -contract Targeted { - bool public world = true; - - function change() public { - world = false; - } -} - -contract Hello { - bool public world = true; - - function no_change() public {} -} - -contract TargetArtifacts is DSTest { - Targeted target1; - Targeted target2; - Hello hello; - - function setUp() public { - target1 = new Targeted(); - target2 = new Targeted(); - hello = new Hello(); - } - - function targetArtifacts() public returns (string[] memory) { - string[] memory abis = new string[](1); - abis[0] = "default/fuzz/invariant/targetAbi/TargetArtifacts.t.sol:Targeted"; - return abis; - } - - function invariantShouldPass() public { - require(target2.world() == true || target1.world() == true || hello.world() == true, "false world"); - } - - function invariantShouldFail() public { - require(target2.world() == true || target1.world() == true, "false world"); - } -} diff --git a/testdata/default/inline/FuzzInlineConf.t.sol b/testdata/default/inline/FuzzInlineConf.t.sol index 73d2de2fc4ed1..24c059e935be7 100644 --- a/testdata/default/inline/FuzzInlineConf.t.sol +++ b/testdata/default/inline/FuzzInlineConf.t.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; +import "utils/Test.sol"; -contract FuzzInlineConf is DSTest { +contract FuzzInlineConf is Test { /** * forge-config: default.fuzz.runs = 1024 * forge-config: default.fuzz.max-test-rejects = 500 @@ -14,7 +14,7 @@ contract FuzzInlineConf is DSTest { } /// forge-config: default.fuzz.runs = 10 -contract FuzzInlineConf2 is DSTest { +contract FuzzInlineConf2 is Test { /// forge-config: default.fuzz.runs = 1 function testInlineConfFuzz1(uint8 x) public { require(true, "this is not going to revert"); diff --git a/testdata/default/inline/InvariantInlineConf.t.sol b/testdata/default/inline/InvariantInlineConf.t.sol index 5ac81755e998d..6699008a343ac 100644 --- a/testdata/default/inline/InvariantInlineConf.t.sol +++ b/testdata/default/inline/InvariantInlineConf.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; +import "utils/Test.sol"; contract InvariantBreaker { bool public flag0 = true; @@ -22,7 +22,7 @@ contract InvariantBreaker { } } -contract InvariantInlineConf is DSTest { +contract InvariantInlineConf is Test { InvariantBreaker inv; function setUp() public { @@ -38,7 +38,7 @@ contract InvariantInlineConf is DSTest { } } -contract InvariantInlineConf2 is DSTest { +contract InvariantInlineConf2 is Test { InvariantBreaker inv; function setUp() public { diff --git a/testdata/default/linking/duplicate/Duplicate.t.sol b/testdata/default/linking/duplicate/Duplicate.t.sol index d1d0f32789238..2ad1d9f7fbe5b 100644 --- a/testdata/default/linking/duplicate/Duplicate.t.sol +++ b/testdata/default/linking/duplicate/Duplicate.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; +import "utils/Test.sol"; // Linking scenario: contract has many dependencies, some of which appear to the linker // more than once. @@ -93,7 +93,7 @@ contract LibraryConsumer { } } -contract DuplicateLibraryLinkingTest is DSTest { +contract DuplicateLibraryLinkingTest is Test { LibraryConsumer consumer; function setUp() public { diff --git a/testdata/default/linking/nested/Nested.t.sol b/testdata/default/linking/nested/Nested.t.sol index 136cb36479cbf..709bf0143857d 100644 --- a/testdata/default/linking/nested/Nested.t.sol +++ b/testdata/default/linking/nested/Nested.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; +import "utils/Test.sol"; // Linking scenario: contract with a library that depends on a library @@ -27,7 +27,7 @@ contract LibraryConsumer { } } -contract NestedLibraryLinkingTest is DSTest { +contract NestedLibraryLinkingTest is Test { LibraryConsumer consumer; function setUp() public { diff --git a/testdata/default/linking/simple/Simple.t.sol b/testdata/default/linking/simple/Simple.t.sol index 85be791fd2489..ded3efb1694c8 100644 --- a/testdata/default/linking/simple/Simple.t.sol +++ b/testdata/default/linking/simple/Simple.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; +import "utils/Test.sol"; // Linking scenario: contract with one library @@ -17,7 +17,7 @@ contract LibraryConsumer { } } -contract SimpleLibraryLinkingTest is DSTest { +contract SimpleLibraryLinkingTest is Test { LibraryConsumer consumer; function setUp() public { diff --git a/testdata/default/logs/DebugLogs.t.sol b/testdata/default/logs/DebugLogs.t.sol deleted file mode 100644 index b560fd2bfb9ca..0000000000000 --- a/testdata/default/logs/DebugLogs.t.sol +++ /dev/null @@ -1,105 +0,0 @@ -pragma solidity ^0.8.18; - -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract DebugLogsTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - - constructor() { - emit log_uint(0); - } - - function setUp() public { - emit log_uint(1); - } - - function test1() public { - emit log_uint(2); - } - - function test2() public { - emit log_uint(3); - } - - function testRevertIfWithRevert() public { - Fails fails = new Fails(); - emit log_uint(4); - vm.expectRevert(); - fails.failure(); - } - - /// forge-config: default.allow_internal_expect_revert = true - function testRevertIfWithRequire() public { - emit log_uint(5); - vm.expectRevert(); - require(false); - } - - function testLog() public { - emit log("Error: Assertion Failed"); - } - - function testLogs() public { - emit logs(bytes("abcd")); - } - - function testLogAddress() public { - emit log_address(address(1)); - } - - function testLogBytes32() public { - emit log_bytes32(bytes32("abcd")); - } - - function testLogInt() public { - emit log_int(int256(-31337)); - } - - function testLogBytes() public { - emit log_bytes(bytes("abcd")); - } - - function testLogString() public { - emit log_string("here"); - } - - function testLogNamedAddress() public { - emit log_named_address("address", address(1)); - } - - function testLogNamedBytes32() public { - emit log_named_bytes32("abcd", bytes32("abcd")); - } - - function testLogNamedDecimalInt() public { - emit log_named_decimal_int("amount", int256(-31337), uint256(18)); - } - - function testLogNamedDecimalUint() public { - emit log_named_decimal_uint("amount", uint256(1 ether), uint256(18)); - } - - function testLogNamedInt() public { - emit log_named_int("amount", int256(-31337)); - } - - function testLogNamedUint() public { - emit log_named_uint("amount", uint256(1 ether)); - } - - function testLogNamedBytes() public { - emit log_named_bytes("abcd", bytes("abcd")); - } - - function testLogNamedString() public { - emit log_named_string("key", "val"); - } -} - -contract Fails is DSTest { - function failure() public { - emit log_uint(100); - revert(); - } -} diff --git a/testdata/default/logs/HardhatLogs.t.sol b/testdata/default/logs/HardhatLogs.t.sol deleted file mode 100644 index a6226bbd665fe..0000000000000 --- a/testdata/default/logs/HardhatLogs.t.sol +++ /dev/null @@ -1,238 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.18; - -import "./console.sol"; - -contract HardhatLogsTest { - constructor() { - console.log("constructor"); - } - - string testStr; - int256 testInt; - uint256 testUint; - bool testBool; - address testAddr; - bytes testBytes; - - function setUp() public { - testStr = "test"; - testInt = -31337; - testUint = 1; - testBool = false; - testAddr = 0x0000000000000000000000000000000000000001; - testBytes = "a"; - } - - function testInts() public view { - console.log(uint256(0)); - console.log(uint256(1)); - console.log(uint256(2)); - console.log(uint256(3)); - } - - function testStrings() public view { - console.log("testStrings"); - } - - function testMisc() public view { - console.log("testMisc", address(1)); - console.log("testMisc", uint256(42)); - } - - function testConsoleLog() public view { - console.log(testStr); - } - - function testLogInt() public view { - console.logInt(testInt); - } - - function testLogUint() public view { - console.logUint(testUint); - } - - function testLogString() public view { - console.logString(testStr); - } - - function testLogBool() public view { - console.logBool(testBool); - } - - function testLogAddress() public view { - console.logAddress(testAddr); - } - - function testLogBytes() public view { - console.logBytes(testBytes); - } - - function testLogBytes1() public view { - console.logBytes1(bytes1(testBytes)); - } - - function testLogBytes2() public view { - console.logBytes2(bytes2(testBytes)); - } - - function testLogBytes3() public view { - console.logBytes3(bytes3(testBytes)); - } - - function testLogBytes4() public view { - console.logBytes4(bytes4(testBytes)); - } - - function testLogBytes5() public view { - console.logBytes5(bytes5(testBytes)); - } - - function testLogBytes6() public view { - console.logBytes6(bytes6(testBytes)); - } - - function testLogBytes7() public view { - console.logBytes7(bytes7(testBytes)); - } - - function testLogBytes8() public view { - console.logBytes8(bytes8(testBytes)); - } - - function testLogBytes9() public view { - console.logBytes9(bytes9(testBytes)); - } - - function testLogBytes10() public view { - console.logBytes10(bytes10(testBytes)); - } - - function testLogBytes11() public view { - console.logBytes11(bytes11(testBytes)); - } - - function testLogBytes12() public view { - console.logBytes12(bytes12(testBytes)); - } - - function testLogBytes13() public view { - console.logBytes13(bytes13(testBytes)); - } - - function testLogBytes14() public view { - console.logBytes14(bytes14(testBytes)); - } - - function testLogBytes15() public view { - console.logBytes15(bytes15(testBytes)); - } - - function testLogBytes16() public view { - console.logBytes16(bytes16(testBytes)); - } - - function testLogBytes17() public view { - console.logBytes17(bytes17(testBytes)); - } - - function testLogBytes18() public view { - console.logBytes18(bytes18(testBytes)); - } - - function testLogBytes19() public view { - console.logBytes19(bytes19(testBytes)); - } - - function testLogBytes20() public view { - console.logBytes20(bytes20(testBytes)); - } - - function testLogBytes21() public view { - console.logBytes21(bytes21(testBytes)); - } - - function testLogBytes22() public view { - console.logBytes22(bytes22(testBytes)); - } - - function testLogBytes23() public view { - console.logBytes23(bytes23(testBytes)); - } - - function testLogBytes24() public view { - console.logBytes24(bytes24(testBytes)); - } - - function testLogBytes25() public view { - console.logBytes25(bytes25(testBytes)); - } - - function testLogBytes26() public view { - console.logBytes26(bytes26(testBytes)); - } - - function testLogBytes27() public view { - console.logBytes27(bytes27(testBytes)); - } - - function testLogBytes28() public view { - console.logBytes28(bytes28(testBytes)); - } - - function testLogBytes29() public view { - console.logBytes29(bytes29(testBytes)); - } - - function testLogBytes30() public view { - console.logBytes30(bytes30(testBytes)); - } - - function testLogBytes31() public view { - console.logBytes31(bytes31(testBytes)); - } - - function testLogBytes32() public view { - console.logBytes32(bytes32(testBytes)); - } - - function testConsoleLogUint() public view { - console.log(testUint); - } - - function testConsoleLogString() public view { - console.log(testStr); - } - - function testConsoleLogBool() public view { - console.log(testBool); - } - - function testConsoleLogAddress() public view { - console.log(testAddr); - } - - function testConsoleLogFormatString() public view { - console.log("formatted log str=%s", testStr); - } - - function testConsoleLogFormatUint() public view { - console.log("formatted log uint=%s", testUint); - } - - function testConsoleLogFormatAddress() public view { - console.log("formatted log addr=%s", testAddr); - } - - function testConsoleLogFormatMulti() public view { - console.log("formatted log str=%s uint=%d", testStr, testUint); - } - - function testConsoleLogFormatEscape() public view { - console.log("formatted log %% %s", testStr); - } - - function testConsoleLogFormatSpill() public view { - console.log("formatted log %s", testStr, testUint); - } -} diff --git a/testdata/default/repros/Issue10302.t.sol b/testdata/default/repros/Issue10302.t.sol index c47332cb2872d..c5516804ccd1c 100644 --- a/testdata/default/repros/Issue10302.t.sol +++ b/testdata/default/repros/Issue10302.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract A { function foo() public pure returns (bool) { @@ -10,9 +9,7 @@ contract A { } } -contract Issue10302Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract Issue10302Test is Test { function testDelegateFails() external { vm.createSelectFork("sepolia"); A a = new A(); diff --git a/testdata/default/repros/Issue10477.t.sol b/testdata/default/repros/Issue10477.t.sol index 86d36fc741ef4..29bfcb37ced29 100644 --- a/testdata/default/repros/Issue10477.t.sol +++ b/testdata/default/repros/Issue10477.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract SimpleDelegate { function call(address target, bytes memory data) external returns (bool callResult, bytes memory callData) { @@ -18,9 +17,7 @@ contract Counter { } } -contract Issue10477Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract Issue10477Test is Test { address payable ALICE_ADDRESS = payable(0x70997970C51812dc3A010C7d01b50e0d17dc79C8); uint256 constant ALICE_PK = 0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d; diff --git a/testdata/default/repros/Issue10527.t.sol b/testdata/default/repros/Issue10527.t.sol index fdf62b22db35c..ba92317672f3c 100644 --- a/testdata/default/repros/Issue10527.t.sol +++ b/testdata/default/repros/Issue10527.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract A { event Event1(); @@ -17,12 +16,10 @@ contract A { } } -contract Issue10527Test is DSTest { +contract Issue10527Test is Test { event Event1(); event Event2(); - Vm constant vm = Vm(HEVM_ADDRESS); - A a; function setUp() public { diff --git a/testdata/default/repros/Issue10552.t.sol b/testdata/default/repros/Issue10552.t.sol index e77168f150f4d..d0f6a7713a9b7 100644 --- a/testdata/default/repros/Issue10552.t.sol +++ b/testdata/default/repros/Issue10552.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract Counter { uint256 public number; @@ -21,9 +20,7 @@ contract Counter { } } -contract Issue10552Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract Issue10552Test is Test { Counter public counter; uint256 mainnetId; uint256 opId; diff --git a/testdata/default/repros/Issue10586.t.sol b/testdata/default/repros/Issue10586.t.sol index 3d7eefbf3ac03..24c355abef7ee 100644 --- a/testdata/default/repros/Issue10586.t.sol +++ b/testdata/default/repros/Issue10586.t.sol @@ -1,20 +1,15 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract Target is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract Target is Test { function setChainId() public { vm.chainId(123); } } -contract Issue10586Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract Issue10586Test is Test { Target public target; function setUp() public { diff --git a/testdata/default/repros/Issue10957.t.sol b/testdata/default/repros/Issue10957.t.sol index b41e116da44fa..a8efd20f5cda6 100644 --- a/testdata/default/repros/Issue10957.t.sol +++ b/testdata/default/repros/Issue10957.t.sol @@ -1,13 +1,10 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/10957 -contract Issue10957Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract Issue10957Test is Test { function testCreateSelectForkBlockNumber() public { // Transaction hash from mainnet bytes32 txHash = 0x2e175897d19307c664815129720c8ac3581da6cb92e4cce923996dd59fbb6ffc; diff --git a/testdata/default/repros/Issue11353.t.sol b/testdata/default/repros/Issue11353.t.sol index e5e863a762903..cb89de17a0ada 100644 --- a/testdata/default/repros/Issue11353.t.sol +++ b/testdata/default/repros/Issue11353.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.24; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract Blobhash { function getIndices(uint256[] calldata blobIndices) public view returns (bytes32[] memory) { @@ -18,9 +17,7 @@ contract Blobhash { } // https://github.com/foundry-rs/foundry/issues/11353 -contract Issue11353Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract Issue11353Test is Test { Blobhash public blobhashContract; function setUp() public { diff --git a/testdata/default/repros/Issue11616.t.sol b/testdata/default/repros/Issue11616.t.sol index 9d82dbbdc4ec3..cf2cbb1900faa 100644 --- a/testdata/default/repros/Issue11616.t.sol +++ b/testdata/default/repros/Issue11616.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.24; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract Emit { event A(); @@ -13,8 +12,7 @@ contract Emit { } } -contract Issue11616Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +contract Issue11616Test is Test { Emit public e; function setUp() public { diff --git a/testdata/default/repros/Issue2623.t.sol b/testdata/default/repros/Issue2623.t.sol index 31252cae36c3b..486db1963b190 100644 --- a/testdata/default/repros/Issue2623.t.sol +++ b/testdata/default/repros/Issue2623.t.sol @@ -1,13 +1,10 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/2623 -contract Issue2623Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract Issue2623Test is Test { function testRollFork() public { uint256 fork = vm.createFork("mainnet", 10); vm.selectFork(fork); diff --git a/testdata/default/repros/Issue2629.t.sol b/testdata/default/repros/Issue2629.t.sol index d46868903a60e..b7e1d9ebdb208 100644 --- a/testdata/default/repros/Issue2629.t.sol +++ b/testdata/default/repros/Issue2629.t.sol @@ -1,13 +1,10 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/2629 -contract Issue2629Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract Issue2629Test is Test { function testSelectFork() public { address coinbase = 0x0193d941b50d91BE6567c7eE1C0Fe7AF498b4137; diff --git a/testdata/default/repros/Issue2723.t.sol b/testdata/default/repros/Issue2723.t.sol index b7678df450cb8..58e9ba43f64d8 100644 --- a/testdata/default/repros/Issue2723.t.sol +++ b/testdata/default/repros/Issue2723.t.sol @@ -1,13 +1,10 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/2723 -contract Issue2723Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract Issue2723Test is Test { function testRollFork() public { address coinbase = 0x0193d941b50d91BE6567c7eE1C0Fe7AF498b4137; diff --git a/testdata/default/repros/Issue2851.t.sol b/testdata/default/repros/Issue2851.t.sol deleted file mode 100644 index 7742af4b708e0..0000000000000 --- a/testdata/default/repros/Issue2851.t.sol +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.1; - -import "ds-test/test.sol"; - -contract Backdoor { - uint256 public number = 1; - - function backdoor(uint256 newNumber) public payable { - uint256 x = newNumber - 1; - if (x == 6912213124124531) { - number = 0; - } - } -} - -// https://github.com/foundry-rs/foundry/issues/2851 -contract Issue2851Test is DSTest { - Backdoor back; - - function setUp() public { - back = new Backdoor(); - } - - /// forge-config: default.fuzz.seed = '111' - function invariantNotZero() public { - assertEq(back.number(), 1); - } -} diff --git a/testdata/default/repros/Issue2898.t.sol b/testdata/default/repros/Issue2898.t.sol index a16adf5a350ff..564ef4fa2ef78 100644 --- a/testdata/default/repros/Issue2898.t.sol +++ b/testdata/default/repros/Issue2898.t.sol @@ -1,15 +1,12 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; -import "../logs/console.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/2898 -contract Issue2898Test is DSTest { +contract Issue2898Test is Test { address private constant BRIDGE = address(10); address private constant BENEFICIARY = address(11); - Vm constant vm = Vm(HEVM_ADDRESS); function setUp() public { vm.deal(BRIDGE, 100); diff --git a/testdata/default/repros/Issue2956.t.sol b/testdata/default/repros/Issue2956.t.sol index c57b46cc1f4bc..3295df41dbf36 100644 --- a/testdata/default/repros/Issue2956.t.sol +++ b/testdata/default/repros/Issue2956.t.sol @@ -1,12 +1,10 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/2956 -contract Issue2956Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +contract Issue2956Test is Test { uint256 fork1; uint256 fork2; diff --git a/testdata/default/repros/Issue2984.t.sol b/testdata/default/repros/Issue2984.t.sol index fbcd1ab8c3c4a..52a3c52d06a84 100644 --- a/testdata/default/repros/Issue2984.t.sol +++ b/testdata/default/repros/Issue2984.t.sol @@ -1,12 +1,10 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/2984 -contract Issue2984Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +contract Issue2984Test is Test { uint256 fork; uint256 snapshot; diff --git a/testdata/default/repros/Issue3055.t.sol b/testdata/default/repros/Issue3055.t.sol deleted file mode 100644 index 90ac8c3b08afd..0000000000000 --- a/testdata/default/repros/Issue3055.t.sol +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.18; - -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -// https://github.com/foundry-rs/foundry/issues/3055 -contract Issue3055Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - - function test_snapshot() external { - uint256 snapshotId = vm.snapshotState(); - assertEq(uint256(0), uint256(1)); - vm.revertToState(snapshotId); - } - - function test_snapshot2() public { - uint256 snapshotId = vm.snapshotState(); - assertTrue(false); - vm.revertToState(snapshotId); - assertTrue(true); - } - - function test_snapshot3(uint256) public { - vm.expectRevert(); - // Call exposed_snapshot3() using this to perform an external call, - // so we can properly test for reverts. - this.exposed_snapshot3(); - } - - function exposed_snapshot3() public { - uint256 snapshotId = vm.snapshotState(); - assertTrue(false); - vm.revertToState(snapshotId); - } -} diff --git a/testdata/default/repros/Issue3077.t.sol b/testdata/default/repros/Issue3077.t.sol index 3b5e4257a3ad4..ec68bc3f4bf63 100644 --- a/testdata/default/repros/Issue3077.t.sol +++ b/testdata/default/repros/Issue3077.t.sol @@ -1,13 +1,10 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/3077 -abstract contract ZeroState is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +abstract contract ZeroState is Test { // deployer and users address public deployer = vm.addr(1); Token aaveToken; diff --git a/testdata/default/repros/Issue3110.t.sol b/testdata/default/repros/Issue3110.t.sol index 9f1da8d032ec3..4c4f3d257d5a5 100644 --- a/testdata/default/repros/Issue3110.t.sol +++ b/testdata/default/repros/Issue3110.t.sol @@ -1,13 +1,10 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/3110 -abstract contract ZeroState is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +abstract contract ZeroState is Test { // deployer and users address public deployer = vm.addr(1); Token aaveToken; diff --git a/testdata/default/repros/Issue3119.t.sol b/testdata/default/repros/Issue3119.t.sol index 6c0ceb429d6d6..99de3f7aab7fd 100644 --- a/testdata/default/repros/Issue3119.t.sol +++ b/testdata/default/repros/Issue3119.t.sol @@ -1,13 +1,10 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/3119 -contract Issue3119Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract Issue3119Test is Test { address public owner = vm.addr(1); address public alice = vm.addr(2); diff --git a/testdata/default/repros/Issue3189.t.sol b/testdata/default/repros/Issue3189.t.sol deleted file mode 100644 index 0bcf5ddce8d76..0000000000000 --- a/testdata/default/repros/Issue3189.t.sol +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.18; - -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -// https://github.com/foundry-rs/foundry/issues/3189 -contract MyContract { - function foo(uint256 arg) public returns (uint256) { - return arg + 2; - } -} - -contract MyContractUser is DSTest { - MyContract immutable myContract; - - constructor() { - myContract = new MyContract(); - } - - function foo(uint256 arg) public returns (uint256 ret) { - ret = myContract.foo(arg); - assertEq(ret, arg + 1, "Invariant failed"); - } -} - -contract Issue3189Test is DSTest { - function testFoo() public { - MyContractUser user = new MyContractUser(); - uint256 fooRet = user.foo(123); - } -} diff --git a/testdata/default/repros/Issue3190.t.sol b/testdata/default/repros/Issue3190.t.sol index ede3e50e2e3ec..30a6bb623b8a1 100644 --- a/testdata/default/repros/Issue3190.t.sol +++ b/testdata/default/repros/Issue3190.t.sol @@ -1,14 +1,10 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; -import "../logs/console.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/3190 -contract Issue3190Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract Issue3190Test is Test { function setUp() public { vm.chainId(99); assertEq(99, block.chainid); diff --git a/testdata/default/repros/Issue3192.t.sol b/testdata/default/repros/Issue3192.t.sol index 9c5be8d89f3d6..6fa3e8dfd442c 100644 --- a/testdata/default/repros/Issue3192.t.sol +++ b/testdata/default/repros/Issue3192.t.sol @@ -1,12 +1,10 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/3192 -contract Issue3192Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +contract Issue3192Test is Test { uint256 fork1; uint256 fork2; diff --git a/testdata/default/repros/Issue3220.t.sol b/testdata/default/repros/Issue3220.t.sol index 5235e44c79c60..366c079619d84 100644 --- a/testdata/default/repros/Issue3220.t.sol +++ b/testdata/default/repros/Issue3220.t.sol @@ -1,12 +1,10 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/3220 -contract Issue3220Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +contract Issue3220Test is Test { IssueRepro repro; uint256 fork1; diff --git a/testdata/default/repros/Issue3221.t.sol b/testdata/default/repros/Issue3221.t.sol index 81398c41fc290..9526987ddd87b 100644 --- a/testdata/default/repros/Issue3221.t.sol +++ b/testdata/default/repros/Issue3221.t.sol @@ -1,12 +1,10 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/3221 -contract Issue3221Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +contract Issue3221Test is Test { uint256 fork1; uint256 fork2; diff --git a/testdata/default/repros/Issue3223.t.sol b/testdata/default/repros/Issue3223.t.sol index 6c21b7b3d60b1..ede3042ba732f 100644 --- a/testdata/default/repros/Issue3223.t.sol +++ b/testdata/default/repros/Issue3223.t.sol @@ -1,12 +1,11 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/3223 -contract Issue3223Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +/// forge-config: default.sender = "0xF0959944122fb1ed4CfaBA645eA06EED30427BAA" +contract Issue3223Test is Test { uint256 fork1; uint256 fork2; diff --git a/testdata/default/repros/Issue3347.t.sol b/testdata/default/repros/Issue3347.t.sol deleted file mode 100644 index e48c1305db426..0000000000000 --- a/testdata/default/repros/Issue3347.t.sol +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.18; - -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -// https://github.com/foundry-rs/foundry/issues/3347 -contract Issue3347Test is DSTest { - event log2(uint256, uint256); - - function test() public { - emit log2(1, 2); - } -} diff --git a/testdata/default/repros/Issue3596.t.sol b/testdata/default/repros/Issue3596.t.sol deleted file mode 100644 index b0c6785874375..0000000000000 --- a/testdata/default/repros/Issue3596.t.sol +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.18; - -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -// https://github.com/foundry-rs/foundry/issues/3596 -contract Issue3596Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - - function testDealTransfer() public { - address addr = vm.addr(1337); - vm.startPrank(addr); - vm.deal(addr, 20000001 ether); - payable(address(this)).transfer(20000000 ether); - - Nested nested = new Nested(); - nested.doStuff(); - vm.stopPrank(); - } -} - -contract Nested { - function doStuff() public { - doRevert(); - } - - function doRevert() public { - revert("This fails"); - } -} diff --git a/testdata/default/repros/Issue3653.t.sol b/testdata/default/repros/Issue3653.t.sol index 26eb38e4a29f1..0657e9908d306 100644 --- a/testdata/default/repros/Issue3653.t.sol +++ b/testdata/default/repros/Issue3653.t.sol @@ -1,12 +1,10 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/3653 -contract Issue3653Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +contract Issue3653Test is Test { uint256 fork; Token token; diff --git a/testdata/default/repros/Issue3661.t.sol b/testdata/default/repros/Issue3661.t.sol index 76b55a222ca00..8491857074e07 100644 --- a/testdata/default/repros/Issue3661.t.sol +++ b/testdata/default/repros/Issue3661.t.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/3661 -contract Issue3661Test is DSTest { +contract Issue3661Test is Test { address sender; function setUp() public { diff --git a/testdata/default/repros/Issue3674.t.sol b/testdata/default/repros/Issue3674.t.sol index de5a960059f52..39d8d9c24f582 100644 --- a/testdata/default/repros/Issue3674.t.sol +++ b/testdata/default/repros/Issue3674.t.sol @@ -1,17 +1,15 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/3674 -contract Issue3674Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +/// forge-config: default.sender = "0xF0959944122fb1ed4CfaBA645eA06EED30427BAA" +contract Issue3674Test is Test { function testNonceCreateSelect() public { vm.createSelectFork("sepolia"); vm.createSelectFork("avaxTestnet"); - assert(vm.getNonce(msg.sender) > 0x17); + assertTrue(vm.getNonce(msg.sender) > 0x17); } } diff --git a/testdata/default/repros/Issue3685.t.sol b/testdata/default/repros/Issue3685.t.sol index f1da5bf6997bd..e7ff00264e52c 100644 --- a/testdata/default/repros/Issue3685.t.sol +++ b/testdata/default/repros/Issue3685.t.sol @@ -1,13 +1,10 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; -import "../logs/console.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/3685 -contract Issue3685Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +contract Issue3685Test is Test { Actor a; Actor b; diff --git a/testdata/default/repros/Issue3703.t.sol b/testdata/default/repros/Issue3703.t.sol index 48651be24c669..3ac50765f1a93 100644 --- a/testdata/default/repros/Issue3703.t.sol +++ b/testdata/default/repros/Issue3703.t.sol @@ -1,14 +1,13 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/3703 -contract Issue3703Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract Issue3703Test is Test { function setUp() public { + vm.skip(true, "flaky polygon RPCs"); + uint256 fork = vm.createSelectFork("polygon", bytes32(0xbed0c8c1b9ff8bf0452979d170c52893bb8954f18a904aa5bcbd0f709be050b9)); } diff --git a/testdata/default/repros/Issue3708.t.sol b/testdata/default/repros/Issue3708.t.sol index 53a7c461f873f..c78304a1cbf02 100644 --- a/testdata/default/repros/Issue3708.t.sol +++ b/testdata/default/repros/Issue3708.t.sol @@ -1,14 +1,12 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/3708 -contract Issue3708Test is DSTest { +contract Issue3708Test is Test { // https://optimistic.etherscan.io/address/0x4e59b44847b379578588920ca78fbf26c0b4956c#code address constant CREATE2_DEPLOYER = 0x4e59b44847b379578588920cA78FbF26c0B4956C; - Vm constant vm = Vm(HEVM_ADDRESS); function setUp() public { uint256 forkId = vm.createSelectFork("optimism"); diff --git a/testdata/default/repros/Issue3753.t.sol b/testdata/default/repros/Issue3753.t.sol index 2c927c823dbb6..1fe6040f2a44a 100644 --- a/testdata/default/repros/Issue3753.t.sol +++ b/testdata/default/repros/Issue3753.t.sol @@ -1,13 +1,10 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/3753 -contract Issue3753Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract Issue3753Test is Test { function test_repro() public { bool res; assembly { diff --git a/testdata/default/repros/Issue3792.t.sol b/testdata/default/repros/Issue3792.t.sol index 37f62bc61fabe..39d3f77bc28a4 100644 --- a/testdata/default/repros/Issue3792.t.sol +++ b/testdata/default/repros/Issue3792.t.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/DSTest.sol"; +import "utils/Vm.sol"; contract Config { address public test = 0xcBa28b38103307Ec8dA98377ffF9816C164f9AFa; diff --git a/testdata/default/repros/Issue4232.t.sol b/testdata/default/repros/Issue4232.t.sol index 0ac6a77c77076..44f038bfbf28e 100644 --- a/testdata/default/repros/Issue4232.t.sol +++ b/testdata/default/repros/Issue4232.t.sol @@ -1,13 +1,10 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/4232 -contract Issue4232Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract Issue4232Test is Test { function testFork() public { // Smoke test, worked previously as well vm.createSelectFork("sepolia", 7215400); diff --git a/testdata/default/repros/Issue4402.t.sol b/testdata/default/repros/Issue4402.t.sol index 830b2926ef269..19072638e74da 100644 --- a/testdata/default/repros/Issue4402.t.sol +++ b/testdata/default/repros/Issue4402.t.sol @@ -1,13 +1,10 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/4402 -contract Issue4402Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract Issue4402Test is Test { function testReadNonEmptyArray() public { string memory path = "fixtures/Json/Issue4402.json"; string memory json = vm.readFile(path); diff --git a/testdata/default/repros/Issue4586.t.sol b/testdata/default/repros/Issue4586.t.sol index c904af1e46abb..57f1dd3052d04 100644 --- a/testdata/default/repros/Issue4586.t.sol +++ b/testdata/default/repros/Issue4586.t.sol @@ -1,13 +1,10 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/4586 -contract Issue4586Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract Issue4586Test is Test { uint256 constant initialBlock = 16730733; InvariantHandler handler; @@ -31,8 +28,7 @@ contract Issue4586Test is DSTest { } contract InvariantHandler { - address constant HEVM_ADDRESS = address(bytes20(uint160(uint256(keccak256("hevm cheat code"))))); - Vm constant vm = Vm(HEVM_ADDRESS); + Vm constant vm = Vm(address(bytes20(uint160(uint256(keccak256("hevm cheat code")))))); uint256 public calledRollFork; diff --git a/testdata/default/repros/Issue4630.t.sol b/testdata/default/repros/Issue4630.t.sol index 01eb626505cd1..cfc0ebde43089 100644 --- a/testdata/default/repros/Issue4630.t.sol +++ b/testdata/default/repros/Issue4630.t.sol @@ -1,13 +1,10 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/4630 -contract Issue4630Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract Issue4630Test is Test { function testExistingValue() public { string memory path = "fixtures/Json/Issue4630.json"; string memory json = vm.readFile(path); diff --git a/testdata/default/repros/Issue4640.t.sol b/testdata/default/repros/Issue4640.t.sol index 1e7d887a9b57d..3a20eaa0f8d8c 100644 --- a/testdata/default/repros/Issue4640.t.sol +++ b/testdata/default/repros/Issue4640.t.sol @@ -1,13 +1,10 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/4640 -contract Issue4640Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract Issue4640Test is Test { function testArbitrumBlockNumber() public { // vm.createSelectFork("arbitrum", 75219831); diff --git a/testdata/default/repros/Issue5038.t.sol b/testdata/default/repros/Issue5038.t.sol index 51a90bca10d4c..2139639cc56ac 100644 --- a/testdata/default/repros/Issue5038.t.sol +++ b/testdata/default/repros/Issue5038.t.sol @@ -1,17 +1,14 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; struct Value { uint256 value; } // https://github.com/foundry-rs/foundry/issues/5038 -contract Issue5038Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract Issue5038Test is Test { function testParseMaxUint64() public { string memory json = '{"value": 18446744073709551615}'; bytes memory parsed = vm.parseJson(json); diff --git a/testdata/default/repros/Issue5529.t.sol b/testdata/default/repros/Issue5529.t.sol index 14ec7cfdbce60..2f7afbbc2d524 100644 --- a/testdata/default/repros/Issue5529.t.sol +++ b/testdata/default/repros/Issue5529.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.13; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract Counter { uint256 public number; @@ -16,20 +15,21 @@ contract Counter { } } -contract Issue5529Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +/// forge-config: default.always_use_create_2_factory = true +contract Issue5529Test is Test { Counter public counter; address public constant default_create2_factory = 0x4e59b44847b379578588920cA78FbF26c0B4956C; function testCreate2FactoryUsedInTests() public { - address a = vm.computeCreate2Address(0, keccak256(type(Counter).creationCode), address(default_create2_factory)); - address b = address(new Counter{salt: 0}()); - require(a == b, "create2 address mismatch"); + run(); } function testCreate2FactoryUsedWhenPranking() public { vm.startPrank(address(1234)); + run(); + } + + function run() private { address a = vm.computeCreate2Address(0, keccak256(type(Counter).creationCode), address(default_create2_factory)); address b = address(new Counter{salt: 0}()); require(a == b, "create2 address mismatch"); diff --git a/testdata/default/repros/Issue5739.t.sol b/testdata/default/repros/Issue5739.t.sol index 6f3494b7e6e7d..bbde1b73e7c20 100644 --- a/testdata/default/repros/Issue5739.t.sol +++ b/testdata/default/repros/Issue5739.t.sol @@ -1,16 +1,14 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; interface IERC20 { function totalSupply() external view returns (uint256 supply); } // https://github.com/foundry-rs/foundry/issues/5739 -contract Issue5739Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +contract Issue5739Test is Test { IERC20 dai; function setUp() public { diff --git a/testdata/default/repros/Issue5808.t.sol b/testdata/default/repros/Issue5808.t.sol index 40efe65a9ce69..fc76fe1e4a3cf 100644 --- a/testdata/default/repros/Issue5808.t.sol +++ b/testdata/default/repros/Issue5808.t.sol @@ -1,13 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/5808 -contract Issue5808Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract Issue5808Test is Test { function testReadInt() public { string memory str1 = '["ffffffff","00000010"]'; vm._expectCheatcodeRevert(); diff --git a/testdata/default/repros/Issue5929.t.sol b/testdata/default/repros/Issue5929.t.sol index ced9d6d9b4a39..6dac42653e3ed 100644 --- a/testdata/default/repros/Issue5929.t.sol +++ b/testdata/default/repros/Issue5929.t.sol @@ -1,13 +1,10 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/5929 -contract Issue5929Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract Issue5929Test is Test { function test_transact_not_working() public { vm.createSelectFork("mainnet", 21134547); // https://etherscan.io/tx/0x96a129768ec66fd7d65114bf182f4e173bf0b73a44219adaf71f01381a3d0143 diff --git a/testdata/default/repros/Issue5935.t.sol b/testdata/default/repros/Issue5935.t.sol index 8ef724412ce31..220681cab55fb 100644 --- a/testdata/default/repros/Issue5935.t.sol +++ b/testdata/default/repros/Issue5935.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract SimpleStorage { uint256 public value; @@ -12,9 +11,7 @@ contract SimpleStorage { } } -contract Issue5935Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract Issue5935Test is Test { function testFork() public { uint256 forkId1 = vm.createFork("mainnet", 18234083); uint256 forkId2 = vm.createFork("mainnet", 18234083); diff --git a/testdata/default/repros/Issue5948.t.sol b/testdata/default/repros/Issue5948.t.sol index ae6ee9d50d8ba..b7a5080721baf 100644 --- a/testdata/default/repros/Issue5948.t.sol +++ b/testdata/default/repros/Issue5948.t.sol @@ -1,13 +1,10 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/5948 -contract Issue5948Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract Issue5948Test is Test { /// forge-config: default.fuzz.runs = 2 function testSleepFuzzed(uint256 _milliseconds) public { // Limit sleep time to 2 seconds to decrease test time diff --git a/testdata/default/repros/Issue6006.t.sol b/testdata/default/repros/Issue6006.t.sol index 54f0d11376d79..30dcbd00a74a2 100644 --- a/testdata/default/repros/Issue6006.t.sol +++ b/testdata/default/repros/Issue6006.t.sol @@ -1,13 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/6006 -contract Issue6066Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract Issue6066Test is Test { function test_parse_11e20_sci() public { string memory json = '{"value": 1.1e20}'; bytes memory parsed = vm.parseJson(json); diff --git a/testdata/default/repros/Issue6032.t.sol b/testdata/default/repros/Issue6032.t.sol index 2fa05222d5a54..149097975ad30 100644 --- a/testdata/default/repros/Issue6032.t.sol +++ b/testdata/default/repros/Issue6032.t.sol @@ -1,13 +1,10 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/6032 -contract Issue6032Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract Issue6032Test is Test { function testEtchFork() public { // Deploy initial contract Counter counter = new Counter(); diff --git a/testdata/default/repros/Issue6070.t.sol b/testdata/default/repros/Issue6070.t.sol index ebf3c7ab15c7b..5188a877e8d90 100644 --- a/testdata/default/repros/Issue6070.t.sol +++ b/testdata/default/repros/Issue6070.t.sol @@ -1,13 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/6070 -contract Issue6066Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract Issue6066Test is Test { function testNonPrefixed() public { vm.setEnv("__FOUNDRY_ISSUE_6066", "abcd"); vm._expectCheatcodeRevert( diff --git a/testdata/default/repros/Issue6115.t.sol b/testdata/default/repros/Issue6115.t.sol index ae65a7dae8647..878b584a31afb 100644 --- a/testdata/default/repros/Issue6115.t.sol +++ b/testdata/default/repros/Issue6115.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.18; -import "ds-test/test.sol"; +import "utils/Test.sol"; contract Counter { uint256 public number; @@ -16,7 +16,7 @@ contract Counter { } // https://github.com/foundry-rs/foundry/issues/6115 -contract Issue6115Test is DSTest { +contract Issue6115Test is Test { Counter public counter; function setUp() public { diff --git a/testdata/default/repros/Issue6170.t.sol b/testdata/default/repros/Issue6170.t.sol deleted file mode 100644 index 78511f4a2dc91..0000000000000 --- a/testdata/default/repros/Issue6170.t.sol +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.18; - -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract Emitter { - event Values(uint256 indexed a, uint256 indexed b); - - function plsEmit(uint256 a, uint256 b) external { - emit Values(a, b); - } -} - -// https://github.com/foundry-rs/foundry/issues/6170 -contract Issue6170Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - - event Values(uint256 indexed a, uint256 b); - - Emitter e = new Emitter(); - - function test() public { - vm.expectEmit(true, true, false, true); - emit Values(69, 420); - e.plsEmit(69, 420); - } -} diff --git a/testdata/default/repros/Issue6180.t.sol b/testdata/default/repros/Issue6180.t.sol index 3d08ccbebac5d..5d6b82988e139 100644 --- a/testdata/default/repros/Issue6180.t.sol +++ b/testdata/default/repros/Issue6180.t.sol @@ -1,13 +1,10 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/6180 -contract Issue6180Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract Issue6180Test is Test { function test_timebug() external { uint256 start = block.timestamp; uint256 count = 4; diff --git a/testdata/default/repros/Issue6293.t.sol b/testdata/default/repros/Issue6293.t.sol index 6d57d13850950..78fe026c3dbf3 100644 --- a/testdata/default/repros/Issue6293.t.sol +++ b/testdata/default/repros/Issue6293.t.sol @@ -1,13 +1,10 @@ // SPDX-License-Identifier: Unlicense pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/6293 -contract Issue6293Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract Issue6293Test is Test { constructor() { require(address(this).balance > 0); payable(address(1)).call{value: 1}(""); diff --git a/testdata/default/repros/Issue6355.t.sol b/testdata/default/repros/Issue6355.t.sol deleted file mode 100644 index bbc3a4a98d412..0000000000000 --- a/testdata/default/repros/Issue6355.t.sol +++ /dev/null @@ -1,39 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.18; - -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -// https://github.com/foundry-rs/foundry/issues/6355 -contract Issue6355Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - uint256 snapshotId; - Target targ; - - function setUp() public { - snapshotId = vm.snapshotState(); - targ = new Target(); - } - - // this non-deterministically fails sometimes and passes sometimes - function test_shouldPass() public { - assertEq(2, targ.num()); - } - - // always fails - function test_shouldFailWithRevertToState() public { - assertEq(3, targ.num()); - vm.revertToState(snapshotId); - } - - // always fails - function test_shouldFail() public { - assertEq(3, targ.num()); - } -} - -contract Target { - function num() public pure returns (uint256) { - return 2; - } -} diff --git a/testdata/default/repros/Issue6437.t.sol b/testdata/default/repros/Issue6437.t.sol index 4cf27be7b233e..e2fceaa660f2a 100644 --- a/testdata/default/repros/Issue6437.t.sol +++ b/testdata/default/repros/Issue6437.t.sol @@ -1,13 +1,10 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/6437 -contract Issue6437Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract Issue6437Test is Test { function test0() public { string memory json = "[]"; address[] memory arr = vm.parseJsonAddressArray(json, "$"); diff --git a/testdata/default/repros/Issue6501.t.sol b/testdata/default/repros/Issue6501.t.sol deleted file mode 100644 index 5d631cbe3e0a8..0000000000000 --- a/testdata/default/repros/Issue6501.t.sol +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.18; - -import "ds-test/test.sol"; -import "../logs/console.sol"; - -// https://github.com/foundry-rs/foundry/issues/6501 -contract Issue6501Test is DSTest { - function test_hhLogs() public { - console.log("a"); - console.log(uint256(1)); - console.log("b", uint256(2)); - } -} diff --git a/testdata/default/repros/Issue6538.t.sol b/testdata/default/repros/Issue6538.t.sol index 34c4e2253a68b..c870c668e6816 100644 --- a/testdata/default/repros/Issue6538.t.sol +++ b/testdata/default/repros/Issue6538.t.sol @@ -1,13 +1,10 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/6538 -contract Issue6538Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract Issue6538Test is Test { function test_transact() public { bytes32 lastHash = 0x4b70ca8c5a0990b43df3064372d424d46efa41dfaab961754b86c5afb2df4f61; vm.createSelectFork("mainnet", lastHash); diff --git a/testdata/default/repros/Issue6554.t.sol b/testdata/default/repros/Issue6554.t.sol index 7a5fe7879c655..a6b086653a96a 100644 --- a/testdata/default/repros/Issue6554.t.sol +++ b/testdata/default/repros/Issue6554.t.sol @@ -1,16 +1,13 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/6554 -contract Issue6554Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract Issue6554Test is Test { function testPermissions() public { - vm.writeFile("./out/default/Issue6554.t.sol/cachedFile.txt", "cached data"); - string memory content = vm.readFile("./out/default/Issue6554.t.sol/cachedFile.txt"); + vm.writeFile("./out/Issue6554.t.sol/cachedFile.txt", "cached data"); + string memory content = vm.readFile("./out/Issue6554.t.sol/cachedFile.txt"); assertEq(content, "cached data"); } } diff --git a/testdata/default/repros/Issue6616.t.sol b/testdata/default/repros/Issue6616.t.sol index 262721d86d118..587c4703e3d6c 100644 --- a/testdata/default/repros/Issue6616.t.sol +++ b/testdata/default/repros/Issue6616.t.sol @@ -1,13 +1,10 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/6616 -contract Issue6616Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract Issue6616Test is Test { function testCreateForkRollLatestBlock() public { vm.createSelectFork("mainnet"); uint256 startBlock = block.number; diff --git a/testdata/default/repros/Issue6634.t.sol b/testdata/default/repros/Issue6634.t.sol index aa94922dd1ccb..5426b3f2404ba 100644 --- a/testdata/default/repros/Issue6634.t.sol +++ b/testdata/default/repros/Issue6634.t.sol @@ -1,9 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; -import "../logs/console.sol"; +import "utils/Test.sol"; contract Box { uint256 public number; @@ -14,9 +12,8 @@ contract Box { } // https://github.com/foundry-rs/foundry/issues/6634 -contract Issue6634Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +/// forge-config: default.always_use_create_2_factory = true +contract Issue6634Test is Test { function test_Create2FactoryCallRecordedInStandardTest() public { address CREATE2_DEPLOYER = 0x4e59b44847b379578588920cA78FbF26c0B4956C; diff --git a/testdata/default/repros/Issue6643.t.sol b/testdata/default/repros/Issue6643.t.sol index 5c7e1c483a03a..0f8b45fa2864d 100644 --- a/testdata/default/repros/Issue6643.t.sol +++ b/testdata/default/repros/Issue6643.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract Counter { event TestEvent(uint256 n); @@ -24,8 +23,7 @@ contract Counter { } // https://github.com/foundry-rs/foundry/issues/6643 -contract Issue6643Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +contract Issue6643Test is Test { Counter public counter; event TestEvent(uint256 n); diff --git a/testdata/default/repros/Issue6759.t.sol b/testdata/default/repros/Issue6759.t.sol index ffdcb88935a92..436d7922fe3d2 100644 --- a/testdata/default/repros/Issue6759.t.sol +++ b/testdata/default/repros/Issue6759.t.sol @@ -1,13 +1,10 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/6759 -contract Issue6759Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract Issue6759Test is Test { function testCreateMulti() public { uint256 fork1 = vm.createFork("mainnet", 10); uint256 fork2 = vm.createFork("mainnet", 10); diff --git a/testdata/default/repros/Issue6966.t.sol b/testdata/default/repros/Issue6966.t.sol index 7e35a869ed0fb..9032a51dd63f7 100644 --- a/testdata/default/repros/Issue6966.t.sol +++ b/testdata/default/repros/Issue6966.t.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/6966 // See also https://github.com/RustCrypto/elliptic-curves/issues/988#issuecomment-1817681013 -contract Issue6966Test is DSTest { +contract Issue6966Test is Test { function testEcrecover() public { bytes32 h = 0x0000000000000000000000000000000000000000000000000000000000000000; uint8 v = 27; diff --git a/testdata/default/repros/Issue7238.t.sol b/testdata/default/repros/Issue7238.t.sol index 5291993525009..989b8d5799fb6 100644 --- a/testdata/default/repros/Issue7238.t.sol +++ b/testdata/default/repros/Issue7238.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract Reverter { function doNotRevert() public {} @@ -13,9 +12,7 @@ contract Reverter { } // https://github.com/foundry-rs/foundry/issues/7238 -contract Issue7238Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract Issue7238Test is Test { function testExpectRevertString() public { Reverter reverter = new Reverter(); vm.expectRevert("revert"); diff --git a/testdata/default/repros/Issue7457.t.sol b/testdata/default/repros/Issue7457.t.sol index 13cd033afac9a..c6413ec8cbe4b 100644 --- a/testdata/default/repros/Issue7457.t.sol +++ b/testdata/default/repros/Issue7457.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; interface ITarget { event AnonymousEventEmpty() anonymous; @@ -46,9 +45,7 @@ contract Target is ITarget { } // https://github.com/foundry-rs/foundry/issues/7457 -contract Issue7457Test is DSTest, ITarget { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract Issue7457Test is Test, ITarget { Target public target; function setUp() external { diff --git a/testdata/default/repros/Issue7481.t.sol b/testdata/default/repros/Issue7481.t.sol index c8116b8095aeb..7fc01fde6523a 100644 --- a/testdata/default/repros/Issue7481.t.sol +++ b/testdata/default/repros/Issue7481.t.sol @@ -1,14 +1,11 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/7481 // This test ensures that we don't panic -contract Issue7481Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract Issue7481Test is Test { /// forge-config: default.allow_internal_expect_revert = true function testRevertTransact() public { vm.expectRevert("vm.createSelectFork: invalid rpc url: mainnet"); diff --git a/testdata/default/repros/Issue8004.t.sol b/testdata/default/repros/Issue8004.t.sol index 278aa12125ff3..b7dd82af36cec 100644 --- a/testdata/default/repros/Issue8004.t.sol +++ b/testdata/default/repros/Issue8004.t.sol @@ -1,11 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; -contract NonPersistentHelper is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +contract NonPersistentHelper is Test { uint256 public curState; function createSelectFork() external { @@ -42,8 +40,7 @@ contract NonPersistentHelper is DSTest { } // https://github.com/foundry-rs/foundry/issues/8004 -contract Issue8004CreateSelectForkTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +contract Issue8004CreateSelectForkTest is Test { NonPersistentHelper helper; function setUp() public { @@ -72,8 +69,7 @@ contract Issue8004CreateSelectForkTest is DSTest { } } -contract Issue8004RollForkTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +contract Issue8004RollForkTest is Test { NonPersistentHelper helper; uint256 forkId; diff --git a/testdata/default/repros/Issue8006.t.sol b/testdata/default/repros/Issue8006.t.sol index efe339d9fef2b..706703eecf8ba 100644 --- a/testdata/default/repros/Issue8006.t.sol +++ b/testdata/default/repros/Issue8006.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; interface IERC20 { function totalSupply() external view returns (uint256 supply); @@ -15,8 +14,7 @@ contract Mock { } // https://github.com/foundry-rs/foundry/issues/8006 -contract Issue8006Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +contract Issue8006Test is Test { IERC20 dai; bytes32 transaction = 0xb23f389b26eb6f95c08e275ec2c360ab3990169492ff0d3e7b7233a3f81d299f; diff --git a/testdata/default/repros/Issue8168.t.sol b/testdata/default/repros/Issue8168.t.sol index 9a072ce4bbf8f..f7871b4b76f71 100644 --- a/testdata/default/repros/Issue8168.t.sol +++ b/testdata/default/repros/Issue8168.t.sol @@ -1,13 +1,10 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/8168 -contract Issue8168Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract Issue8168Test is Test { function testForkWarpRollPreserved() public { uint256 fork1 = vm.createFork("mainnet"); uint256 fork2 = vm.createFork("mainnet"); diff --git a/testdata/default/repros/Issue8277.t.sol b/testdata/default/repros/Issue8277.t.sol index 48a089575b402..8dca9cd7ea832 100644 --- a/testdata/default/repros/Issue8277.t.sol +++ b/testdata/default/repros/Issue8277.t.sol @@ -1,13 +1,10 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/8277 -contract Issue8277Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract Issue8277Test is Test { struct MyJson { string s; } diff --git a/testdata/default/repros/Issue8287.t.sol b/testdata/default/repros/Issue8287.t.sol index d1e372bda91d8..e1a67f3538e46 100644 --- a/testdata/default/repros/Issue8287.t.sol +++ b/testdata/default/repros/Issue8287.t.sol @@ -1,13 +1,10 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/8287 -contract Issue8287Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract Issue8287Test is Test { function testRpcBalance() public { uint256 f2 = vm.createSelectFork("mainnet", 10); bytes memory data = vm.rpc("eth_getBalance", "[\"0x551e7784778ef8e048e495df49f2614f84a4f1dc\",\"0x0\"]"); diff --git a/testdata/default/repros/Issue8566.t.sol b/testdata/default/repros/Issue8566.t.sol index f300d096f7a22..2dad2fc1f8371 100644 --- a/testdata/default/repros/Issue8566.t.sol +++ b/testdata/default/repros/Issue8566.t.sol @@ -1,13 +1,10 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; // https://github.com/foundry-rs/foundry/issues/8566 -contract Issue8566Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract Issue8566Test is Test { function testParseJsonUint() public { string memory json = "{ \"1284\": { \"addRewardInfo\": { \"amount\": 74258.225772486694040708e18, \"rewardPerSec\": 0.03069536448928848133e20 } } }"; diff --git a/testdata/default/repros/Issue8639.t.sol b/testdata/default/repros/Issue8639.t.sol index 6f0a7b526336f..96b2fa3621522 100644 --- a/testdata/default/repros/Issue8639.t.sol +++ b/testdata/default/repros/Issue8639.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; +import "utils/Test.sol"; library ExternalLibrary { function doWork(uint256 a) public returns (uint256) { @@ -20,7 +20,7 @@ contract Counter { } // https://github.com/foundry-rs/foundry/issues/8639 -contract Issue8639Test is DSTest { +contract Issue8639Test is Test { Counter counter; function setUp() public { @@ -28,15 +28,15 @@ contract Issue8639Test is DSTest { } /// forge-config: default.fuzz.runs = 1000 - /// forge-config: default.fuzz.seed = '100' + /// forge-config: default.fuzz.seed = "100" function test_external_library_address(address test) public { require(test != address(ExternalLibrary)); } } -contract Issue8639AnotherTest is DSTest { +contract Issue8639AnotherTest is Test { /// forge-config: default.fuzz.runs = 1000 - /// forge-config: default.fuzz.seed = '100' + /// forge-config: default.fuzz.seed = "100" function test_another_external_library_address(address test) public { require(test != address(ExternalLibrary)); } diff --git a/testdata/default/repros/Issue8971.t.sol b/testdata/default/repros/Issue8971.t.sol index 37861b483ec5d..4d235be214679 100644 --- a/testdata/default/repros/Issue8971.t.sol +++ b/testdata/default/repros/Issue8971.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract Counter { uint256 public number; @@ -31,7 +30,8 @@ contract Handler { } } -contract Invariant is DSTest { +/// forge-config: default.isolate = true +contract Invariant is Test { Handler h; function setUp() public { diff --git a/testdata/default/repros/Issue9643.t.sol b/testdata/default/repros/Issue9643.t.sol index 5429219e5863d..fead6ebcbb0c4 100644 --- a/testdata/default/repros/Issue9643.t.sol +++ b/testdata/default/repros/Issue9643.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract Mock { uint256 private counter; @@ -33,16 +32,14 @@ contract DelegateProxy { } } -contract Issue9643Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract Issue9643Test is Test { function test_storage_json_diff() public { vm.startStateDiffRecording(); Mock proxied = Mock(address(new DelegateProxy(address(new Mock())))); proxied.setCounter(42); string memory rawDiff = vm.getStateDiffJson(); assertEq( - "{\"0x2e234dae75c793f67a35089c9d99245e1c58470b\":{\"label\":null,\"contract\":\"default/repros/Issue9643.t.sol:DelegateProxy\",\"balanceDiff\":null,\"nonceDiff\":{\"previousValue\":0,\"newValue\":1},\"stateDiff\":{\"0x0000000000000000000000000000000000000000000000000000000000000000\":{\"previousValue\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"newValue\":\"0x000000000000000000000000000000000000000000000000000000000000002a\"}}},\"0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f\":{\"label\":null,\"contract\":\"default/repros/Issue9643.t.sol:Mock\",\"balanceDiff\":null,\"nonceDiff\":{\"previousValue\":0,\"newValue\":1},\"stateDiff\":{}}}", + '{"0x2e234dae75c793f67a35089c9d99245e1c58470b":{"label":null,"contract":"default/repros/Issue9643.t.sol:DelegateProxy","balanceDiff":null,"nonceDiff":{"previousValue":0,"newValue":1},"stateDiff":{"0x0000000000000000000000000000000000000000000000000000000000000000":{"previousValue":"0x0000000000000000000000000000000000000000000000000000000000000000","newValue":"0x000000000000000000000000000000000000000000000000000000000000002a","label":"implementation","type":"address","offset":0,"slot":"0","decoded":{"previousValue":"0x0000000000000000000000000000000000000000","newValue":"0x000000000000000000000000000000000000002A"}}}},"0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f":{"label":null,"contract":"default/repros/Issue9643.t.sol:Mock","balanceDiff":null,"nonceDiff":{"previousValue":0,"newValue":1},"stateDiff":{}}}', rawDiff ); } diff --git a/testdata/default/spec/ShanghaiCompat.t.sol b/testdata/default/spec/ShanghaiCompat.t.sol index fd7213b3d0702..7ff6405d16ccf 100644 --- a/testdata/default/spec/ShanghaiCompat.t.sol +++ b/testdata/default/spec/ShanghaiCompat.t.sol @@ -1,12 +1,9 @@ // 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); +import "utils/Test.sol"; +contract ShanghaiCompat is Test { function testPush0() public { address target = address(uint160(uint256(0xc4f3))); diff --git a/testdata/default/trace/ConflictingSignatures.t.sol b/testdata/default/trace/ConflictingSignatures.t.sol deleted file mode 100644 index c8b7066c7a2f1..0000000000000 --- a/testdata/default/trace/ConflictingSignatures.t.sol +++ /dev/null @@ -1,41 +0,0 @@ -pragma solidity ^0.8.18; - -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract ReturnsNothing { - function func() public pure {} -} - -contract ReturnsString { - function func() public pure returns (string memory) { - return "string"; - } -} - -contract ReturnsUint { - function func() public pure returns (uint256) { - return 1; - } -} - -contract ConflictingSignaturesTest is DSTest { - ReturnsNothing retsNothing; - ReturnsString retsString; - ReturnsUint retsUint; - - function setUp() public { - retsNothing = new ReturnsNothing(); - retsString = new ReturnsString(); - retsUint = new ReturnsUint(); - } - - /// Tests that traces are decoded properly when multiple - /// functions have the same 4byte signature, but different - /// return values. - function testTraceWithConflictingSignatures() public { - retsNothing.func(); - retsString.func(); - retsUint.func(); - } -} diff --git a/testdata/default/trace/Trace.t.sol b/testdata/default/trace/Trace.t.sol deleted file mode 100644 index 19af6dd7c9fe7..0000000000000 --- a/testdata/default/trace/Trace.t.sol +++ /dev/null @@ -1,98 +0,0 @@ -pragma solidity ^0.8.18; - -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract RecursiveCall { - TraceTest factory; - - event Depth(uint256 depth); - event ChildDepth(uint256 childDepth); - event CreatedChild(uint256 childDepth); - - constructor(address _factory) { - factory = TraceTest(_factory); - } - - function recurseCall(uint256 neededDepth, uint256 depth) public returns (uint256) { - if (depth == neededDepth) { - this.negativeNum(); - return neededDepth; - } - - uint256 childDepth = this.recurseCall(neededDepth, depth + 1); - emit ChildDepth(childDepth); - - this.someCall(); - emit Depth(depth); - - return depth; - } - - function recurseCreate(uint256 neededDepth, uint256 depth) public returns (uint256) { - if (depth == neededDepth) { - return neededDepth; - } - - RecursiveCall child = factory.create(); - emit CreatedChild(depth + 1); - - uint256 childDepth = child.recurseCreate(neededDepth, depth + 1); - emit ChildDepth(childDepth); - emit Depth(depth); - - return depth; - } - - function someCall() public pure {} - - function negativeNum() public pure returns (int256) { - return -1000000000; - } -} - -contract TraceTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - - uint256 nodeId = 0; - RecursiveCall first; - - function setUp() public { - first = this.create(); - } - - function create() public returns (RecursiveCall) { - RecursiveCall node = new RecursiveCall(address(this)); - vm.label(address(node), string(abi.encodePacked("Node ", uintToString(nodeId++)))); - - return node; - } - - function testRecurseCall() public { - first.recurseCall(8, 0); - } - - function testRecurseCreate() public { - first.recurseCreate(8, 0); - } -} - -function uintToString(uint256 value) pure returns (string memory) { - // Taken from OpenZeppelin - if (value == 0) { - return "0"; - } - uint256 temp = value; - uint256 digits; - while (temp != 0) { - digits++; - temp /= 10; - } - bytes memory buffer = new bytes(digits); - while (value != 0) { - digits -= 1; - buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); - value /= 10; - } - return string(buffer); -} diff --git a/testdata/default/vyper/CounterTest.vy b/testdata/default/vyper/CounterTest.vy index b6cc517d25dd6..960ec5cbaa830 100644 --- a/testdata/default/vyper/CounterTest.vy +++ b/testdata/default/vyper/CounterTest.vy @@ -1,4 +1,4 @@ -from . import ICounter +from src import ICounter interface Vm: def deployCode(artifact_name: String[1024], args: Bytes[1024] = b"") -> address: nonpayable @@ -8,7 +8,7 @@ counter: ICounter @external def setUp(): - self.counter = ICounter(extcall vm.deployCode("vyper/Counter.vy")) + self.counter = ICounter(extcall vm.deployCode("src/Counter.vy")) @external def test_increment(): diff --git a/testdata/fixtures/File/ignored/.gitignore b/testdata/fixtures/File/ignored/.gitignore new file mode 100644 index 0000000000000..9c558e357c416 --- /dev/null +++ b/testdata/fixtures/File/ignored/.gitignore @@ -0,0 +1 @@ +. diff --git a/testdata/foundry.toml b/testdata/foundry.toml index 2360d009c7a09..86700b2584c2f 100644 --- a/testdata/foundry.toml +++ b/testdata/foundry.toml @@ -1,14 +1,60 @@ [profile.default] -src = "./" +src = "src" test = "./" -solc = "0.8.18" -evm_version = "paris" -ffi = false -fs_permissions = [{ access = "read-write", path = "./" }] +optimizer = true +optimizer_runs = 200 +via_ir = false +ignored_error_codes = [ + 1878, # SPDX license identifier not provided + 2018, # Function state mutability can be restricted + 2072, # Unused local variable + 2319, # This declaration shadows a builtin symbol + 2519, # This declaration shadows an existing declaration + 3860, # Contract init code size exceeds limit + 5574, # Contract code size exceeds limit + 5667, # Unused function parameter +] +extra_output = ["storageLayout"] + +additional_compiler_profiles = [ + # paris + { name = "paris", evm_version = "paris" }, +] +compilation_restrictions = [ + # paris + { paths = "paris/**", evm_version = "paris" }, +] + +ffi = true +fs_permissions = [ + { access = "read-write", path = "out/" }, + { access = "read-write", path = "fixtures/" }, +] +verbosity = 3 +prompt_timeout = 0 [profile.default.rpc_storage_caching] chains = "all" endpoints = "all" +[profile.default.invariant] +depth = 15 + [fmt] ignore = ["cheats/Vm.sol"] + +[lint] +lint_on_build = false + +# These are set in .env, which is populated when running through `cargo (nex)test`. +[rpc_endpoints] +mainnet = "${RPC_MAINNET}" +mainnet2 = "${RPC_MAINNET2}" +sepolia = "${RPC_SEPOLIA}" +optimism = "${RPC_OPTIMISM}" +arbitrum = "${RPC_ARBITRUM}" +polygon = "${RPC_POLYGON}" +bsc = "${RPC_BSC}" +avaxTestnet = "https://api.avax-test.network/ext/bc/C/rpc" +moonbeam = "https://moonbeam-rpc.publicnode.com" +rpcEnvAlias = "${RPC_ENV_ALIAS}" diff --git a/testdata/multi-version/Counter.sol b/testdata/multi-version/Counter.sol index 4f0c350335f8e..b2d9774d4b9a8 100644 --- a/testdata/multi-version/Counter.sol +++ b/testdata/multi-version/Counter.sol @@ -1,3 +1,5 @@ +pragma solidity ^0.8.4; + contract Counter { uint256 public number; diff --git a/testdata/multi-version/cheats/GetCode.t.sol b/testdata/multi-version/cheats/GetCode.t.sol index 72dae24e676af..ecb78876cb053 100644 --- a/testdata/multi-version/cheats/GetCode.t.sol +++ b/testdata/multi-version/cheats/GetCode.t.sol @@ -1,13 +1,10 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity =0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; import "../Counter.sol"; -contract GetCodeTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract GetCodeTest is Test { function testGetCodeMultiVersion() public { assertEq(vm.getCode("Counter.sol"), type(Counter).creationCode); require( diff --git a/testdata/multi-version/cheats/GetCode17.t.sol b/testdata/multi-version/cheats/GetCode17.t.sol index f8bf4bb2aee28..3cdd42ef3c78a 100644 --- a/testdata/multi-version/cheats/GetCode17.t.sol +++ b/testdata/multi-version/cheats/GetCode17.t.sol @@ -1,14 +1,11 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity =0.8.17; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; import "../Counter.sol"; // Same as GetCode.t.sol but for 0.8.17 version -contract GetCodeTest17 is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract GetCodeTest17 is Test { function testGetCodeMultiVersion() public { assertEq(vm.getCode("Counter.sol"), type(Counter).creationCode); require( diff --git a/testdata/paris/cheats/Fork.t.sol b/testdata/paris/cheats/Fork.t.sol index 2f2e627de131a..281a27a0b868c 100644 --- a/testdata/paris/cheats/Fork.t.sol +++ b/testdata/paris/cheats/Fork.t.sol @@ -1,19 +1,17 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; interface IWETH { function deposit() external payable; function balanceOf(address) external view returns (uint256); } -contract ForkTest is DSTest { +contract ForkTest is Test { 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; diff --git a/testdata/paris/cheats/GasSnapshots.t.sol b/testdata/paris/cheats/GasSnapshots.t.sol index d4f471fdeaf4d..a3f1c9921a4b5 100644 --- a/testdata/paris/cheats/GasSnapshots.t.sol +++ b/testdata/paris/cheats/GasSnapshots.t.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; - -contract GasSnapshotTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +import "utils/Test.sol"; +contract GasSnapshotTest is Test { uint256 public slot0; Flare public flare; @@ -94,7 +91,7 @@ contract GasSnapshotTest is DSTest { function testSnapshotGasSectionDefaultGroupStop() public { vm.startSnapshotGas("testSnapshotGasSection"); - flare.run(256); + flare.run(8); // vm.stopSnapshotGas() will use the last snapshot name. uint256 gasUsed = vm.stopSnapshotGas(); @@ -105,7 +102,7 @@ contract GasSnapshotTest is DSTest { function testSnapshotGasSectionCustomGroupStop() public { vm.startSnapshotGas("CustomGroup", "testSnapshotGasSection"); - flare.run(256); + flare.run(8); // vm.stopSnapshotGas() will use the last snapshot name, even with custom group. uint256 gasUsed = vm.stopSnapshotGas(); @@ -116,7 +113,7 @@ contract GasSnapshotTest is DSTest { function testSnapshotGasSectionName() public { vm.startSnapshotGas("testSnapshotGasSectionName"); - flare.run(256); + flare.run(8); uint256 gasUsed = vm.stopSnapshotGas("testSnapshotGasSectionName"); assertGt(gasUsed, 0); @@ -126,7 +123,7 @@ contract GasSnapshotTest is DSTest { function testSnapshotGasSectionGroupName() public { vm.startSnapshotGas("CustomGroup", "testSnapshotGasSectionGroupName"); - flare.run(256); + flare.run(8); uint256 gasUsed = vm.stopSnapshotGas("CustomGroup", "testSnapshotGasSectionGroupName"); assertGt(gasUsed, 0); @@ -149,9 +146,7 @@ contract GasSnapshotTest is DSTest { } } -contract GasComparisonTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract GasComparisonTest is Test { uint256 public slot0; uint256 public slot1; @@ -263,12 +258,12 @@ contract GasComparisonTest is DSTest { // Start a cheatcode snapshot. vm.startSnapshotGas("ComparisonGroup", "testGasComparisonFlareA"); - flare.run(256); + flare.run(8); uint256 a = vm.stopSnapshotGas(); // Start a comparative Solidity snapshot. _snapStart(); - flare.run(256); + flare.run(8); uint256 b = _snapEnd(); vm.snapshotValue("ComparisonGroup", "testGasComparisonFlareB", b); diff --git a/testdata/paris/cheats/LastCallGas.t.sol b/testdata/paris/cheats/LastCallGas.t.sol index 23f6df224963f..8c2c20ee8c41e 100644 --- a/testdata/paris/cheats/LastCallGas.t.sol +++ b/testdata/paris/cheats/LastCallGas.t.sol @@ -1,8 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; +import "utils/Test.sol"; contract Target { uint256 public slot0; @@ -28,8 +27,7 @@ contract Target { fallback() external {} } -abstract contract LastCallGasFixture is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); +abstract contract LastCallGasFixture is Test { Target public target; struct Gas { @@ -67,6 +65,7 @@ abstract contract LastCallGasFixture is DSTest { } } +/// forge-config: default.isolate = true contract LastCallGasIsolatedTest is LastCallGasFixture { function testRecordLastCallGas() public { _setup(); diff --git a/testdata/paris/core/BeforeTest.t.sol b/testdata/paris/core/BeforeTest.t.sol index 2b14bcad1d2ef..10acfb53ee88f 100644 --- a/testdata/paris/core/BeforeTest.t.sol +++ b/testdata/paris/core/BeforeTest.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; +import "utils/Test.sol"; contract SelfDestructor { function kill() external { @@ -10,7 +10,7 @@ contract SelfDestructor { } // https://github.com/foundry-rs/foundry/issues/1543 -contract BeforeTestSelfDestructTest is DSTest { +contract BeforeTestSelfDestructTest is Test { SelfDestructor killer; uint256 a; uint256 b; @@ -46,16 +46,18 @@ contract BeforeTestSelfDestructTest is DSTest { function kill_contract() external { uint256 killer_size = getSize(address(killer)); - require(killer_size == 106); + assertEq(killer_size, 106); killer.kill(); + assertEq(killer_size, 106); } - function testKill() public view { + /// forge-config: default.evm_version = "paris" + function testKill() public { uint256 killer_size = getSize(address(killer)); - require(killer_size == 0); + assertEq(killer_size, 0); } - function getSize(address c) public view returns (uint32) { + function getSize(address c) internal view returns (uint32) { uint32 size; assembly { size := extcodesize(c) @@ -64,12 +66,12 @@ contract BeforeTestSelfDestructTest is DSTest { } function testA() public { - require(a <= 3); + assertLe(a, 3); a += 1; } - function testSimpleA() public view { - require(a == 0); + function testSimpleA() public { + assertEq(a, 0); } function setB() public { @@ -77,7 +79,7 @@ contract BeforeTestSelfDestructTest is DSTest { } function testB() public { - require(b == 100); + assertEq(b, 100); } function setBWithValue(uint256 value) public { diff --git a/testdata/paris/fork/Transact.t.sol b/testdata/paris/fork/Transact.t.sol index 92d595f98c516..c543590d6b1be 100644 --- a/testdata/paris/fork/Transact.t.sol +++ b/testdata/paris/fork/Transact.t.sol @@ -1,9 +1,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; -import "ds-test/test.sol"; -import "cheats/Vm.sol"; -import "../../default/logs/console.sol"; +import "utils/Test.sol"; interface IERC20 { function transfer(address to, uint256 amount) external returns (bool); @@ -11,9 +9,7 @@ interface IERC20 { function balanceOf(address account) external view returns (uint256); } -contract TransactOnForkTest is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - +contract TransactOnForkTest is Test { IERC20 constant USDT = IERC20(0xdAC17F958D2ee523a2206206994597C13D831ec7); event Transfer(address indexed from, address indexed to, uint256 value); diff --git a/testdata/paris/spec/ShanghaiCompat.t.sol b/testdata/paris/spec/ShanghaiCompat.t.sol index fd7213b3d0702..7ff6405d16ccf 100644 --- a/testdata/paris/spec/ShanghaiCompat.t.sol +++ b/testdata/paris/spec/ShanghaiCompat.t.sol @@ -1,12 +1,9 @@ // 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); +import "utils/Test.sol"; +contract ShanghaiCompat is Test { function testPush0() public { address target = address(uint160(uint256(0xc4f3))); diff --git a/testdata/default/vyper/Counter.vy b/testdata/src/Counter.vy similarity index 100% rename from testdata/default/vyper/Counter.vy rename to testdata/src/Counter.vy diff --git a/testdata/default/vyper/ICounter.vyi b/testdata/src/ICounter.vyi similarity index 100% rename from testdata/default/vyper/ICounter.vyi rename to testdata/src/ICounter.vyi diff --git a/testdata/lib/ds-test/src/test.sol b/testdata/utils/DSTest.sol similarity index 100% rename from testdata/lib/ds-test/src/test.sol rename to testdata/utils/DSTest.sol diff --git a/testdata/utils/Test.sol b/testdata/utils/Test.sol new file mode 100644 index 0000000000000..6c7930bc3088e --- /dev/null +++ b/testdata/utils/Test.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity >=0.6.2 <0.9.0; +pragma experimental ABIEncoderV2; + +import "./DSTest.sol"; +import "./Vm.sol"; +import "./console.sol"; + +contract Test is DSTest { + Vm public constant vm = Vm(HEVM_ADDRESS); +} diff --git a/testdata/cheats/Vm.sol b/testdata/utils/Vm.sol similarity index 100% rename from testdata/cheats/Vm.sol rename to testdata/utils/Vm.sol diff --git a/testdata/default/logs/console.sol b/testdata/utils/console.sol similarity index 100% rename from testdata/default/logs/console.sol rename to testdata/utils/console.sol From 9a02aa8bab55a637472a9d2e1fe57a233f00d66e Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Fri, 17 Oct 2025 23:21:36 +0700 Subject: [PATCH 103/232] Update test.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .github/workflows/test.yml | 151 ++++++++++--------------------------- 1 file changed, 39 insertions(+), 112 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e71c1d2f993e3..fc858c4bd6f85 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,7 +1,5 @@ name: test -permissions: {} - on: push: branches: @@ -15,31 +13,23 @@ concurrency: env: CARGO_TERM_COLOR: always RUST_BACKTRACE: full - RUSTC_WRAPPER: "sccache" jobs: nextest: uses: ./.github/workflows/nextest.yml - permissions: - contents: read with: profile: default secrets: inherit docs: - runs-on: depot-ubuntu-latest - timeout-minutes: 5 - permissions: - contents: read + runs-on: ubuntu-latest + timeout-minutes: 30 steps: - uses: actions/checkout@v5 + - uses: dtolnay/rust-toolchain@nightly + - uses: Swatinem/rust-cache@v2 with: - persist-credentials: false - - uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # master - with: - toolchain: nightly - - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 - - uses: mozilla-actions/sccache-action@7d986dd989559c6ecdb630a3fd2557667be217ad # v0.0.9 + cache-on-failure: true - name: Build documentation run: cargo doc --workspace --all-features --no-deps --document-private-items env: @@ -47,161 +37,99 @@ jobs: - name: Setup Pages uses: actions/configure-pages@v5 - name: Upload artifact - uses: actions/upload-pages-artifact@v4 + uses: actions/upload-pages-artifact@v3 with: path: ./target/doc deploy-docs: if: github.ref_name == 'master' && github.event_name == 'push' + runs-on: ubuntu-latest needs: [docs] - runs-on: depot-ubuntu-latest - timeout-minutes: 5 + # Grant GITHUB_TOKEN the permissions required to make a Pages deployment permissions: pages: write id-token: write environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} + timeout-minutes: 30 steps: - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@v4 doctest: - runs-on: depot-ubuntu-latest - timeout-minutes: 5 - permissions: - contents: read + runs-on: ubuntu-latest + timeout-minutes: 30 steps: - uses: actions/checkout@v5 + - uses: dtolnay/rust-toolchain@stable + - uses: Swatinem/rust-cache@v2 with: - persist-credentials: false - - uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # master - with: - toolchain: stable - - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 - - uses: mozilla-actions/sccache-action@7d986dd989559c6ecdb630a3fd2557667be217ad # v0.0.9 + cache-on-failure: true - run: cargo test --workspace --doc typos: - runs-on: depot-ubuntu-latest - timeout-minutes: 5 - permissions: - contents: read + runs-on: ubuntu-latest + timeout-minutes: 30 steps: - uses: actions/checkout@v5 - with: - persist-credentials: false - - uses: crate-ci/typos@83157de2df0fa7c7ae20f73f9dbed44c41f2bb64 # v1 + - uses: crate-ci/typos@v1 clippy: - runs-on: depot-ubuntu-latest - timeout-minutes: 5 - permissions: - contents: read + runs-on: ubuntu-latest + timeout-minutes: 30 steps: - uses: actions/checkout@v5 + - uses: dtolnay/rust-toolchain@clippy + - uses: Swatinem/rust-cache@v2 with: - persist-credentials: false - - uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # master - with: - toolchain: nightly - components: clippy - - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 - - uses: mozilla-actions/sccache-action@7d986dd989559c6ecdb630a3fd2557667be217ad # v0.0.9 + cache-on-failure: true - run: cargo clippy --workspace --all-targets --all-features env: RUSTFLAGS: -Dwarnings rustfmt: - runs-on: depot-ubuntu-latest - timeout-minutes: 5 - permissions: - contents: read + runs-on: ubuntu-latest + timeout-minutes: 30 steps: - uses: actions/checkout@v5 + - uses: dtolnay/rust-toolchain@nightly with: - persist-credentials: false - - uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # master - with: - toolchain: nightly components: rustfmt - run: cargo fmt --all --check forge-fmt: - runs-on: depot-ubuntu-latest - timeout-minutes: 5 - permissions: - contents: read + runs-on: ubuntu-latest + timeout-minutes: 30 steps: - uses: actions/checkout@v5 + - uses: dtolnay/rust-toolchain@stable + - uses: Swatinem/rust-cache@v2 with: - persist-credentials: false - - uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # master - with: - toolchain: stable - - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 - - uses: mozilla-actions/sccache-action@7d986dd989559c6ecdb630a3fd2557667be217ad # v0.0.9 + cache-on-failure: true - name: forge fmt shell: bash run: ./.github/scripts/format.sh --check crate-checks: - runs-on: depot-ubuntu-latest - timeout-minutes: 5 - permissions: - contents: read + runs-on: ubuntu-latest + timeout-minutes: 30 steps: - uses: actions/checkout@v5 + - uses: dtolnay/rust-toolchain@stable + - uses: taiki-e/install-action@cargo-hack + - uses: Swatinem/rust-cache@v2 with: - persist-credentials: false - - uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # master - with: - toolchain: stable - - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 - - uses: taiki-e/install-action@e43a5023a747770bfcb71ae048541a681714b951 # v2 - with: - tool: cargo-hack - - uses: mozilla-actions/sccache-action@7d986dd989559c6ecdb630a3fd2557667be217ad # v0.0.9 + cache-on-failure: true - run: cargo hack check deny: - uses: ithacaxyz/ci/.github/workflows/deny.yml@9c8d0dc20e7ad02455d3fdab2378a05f29907630 # main - permissions: - contents: read - - codeql: - name: Analyze (${{ matrix.language }}) - runs-on: ubuntu-latest - permissions: - security-events: write - actions: read - contents: read - strategy: - fail-fast: false - matrix: - include: - - language: actions - build-mode: none - steps: - - name: Checkout repository - uses: actions/checkout@v5 - with: - persist-credentials: false - - name: Initialize CodeQL - uses: github/codeql-action/init@v4 - with: - languages: ${{ matrix.language }} - build-mode: ${{ matrix.build-mode }} - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v4 - with: - category: "/language:${{matrix.language}}" + uses: ithacaxyz/ci/.github/workflows/deny.yml@main ci-success: runs-on: ubuntu-latest if: always() - permissions: {} needs: - nextest - docs @@ -212,10 +140,9 @@ jobs: - forge-fmt - crate-checks - deny - - codeql - timeout-minutes: 5 + timeout-minutes: 30 steps: - name: Decide whether the needed jobs succeeded or failed - uses: re-actors/alls-green@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe # release/v1 + uses: re-actors/alls-green@release/v1 with: jobs: ${{ toJSON(needs) }} From e787d818e5d56fdc15062c697fa57652d1b992f0 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Fri, 17 Oct 2025 17:32:03 +0000 Subject: [PATCH 104/232] Update test.yml (#167) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .github/workflows/test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index fc858c4bd6f85..14265f1325db0 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -146,3 +146,4 @@ jobs: uses: re-actors/alls-green@release/v1 with: jobs: ${{ toJSON(needs) }} + From 99056c7fe5ad4e7eea5cc7fbf999c3353b1ca573 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Fri, 17 Oct 2025 18:31:21 +0000 Subject: [PATCH 105/232] Update test.yml (#168) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .github/workflows/test.yml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a8af345fe28ff..6ce03503a8858 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -29,7 +29,7 @@ jobs: docs: runs-on: depot-ubuntu-latest - timeout-minutes: 5 + timeout-minutes: 30 permissions: contents: read steps: @@ -56,7 +56,7 @@ jobs: if: github.ref_name == 'master' && github.event_name == 'push' needs: [docs] runs-on: depot-ubuntu-latest - timeout-minutes: 5 + timeout-minutes: 30 permissions: pages: write id-token: write @@ -70,7 +70,7 @@ jobs: doctest: runs-on: depot-ubuntu-latest - timeout-minutes: 5 + timeout-minutes: 30 permissions: contents: read steps: @@ -86,18 +86,18 @@ jobs: typos: runs-on: depot-ubuntu-latest - timeout-minutes: 5 + timeout-minutes: 30 permissions: contents: read steps: - uses: actions/checkout@v5 with: persist-credentials: false - - uses: crate-ci/typos@83157de2df0fa7c7ae20f73f9dbed44c41f2bb64 # v1 + - uses: crate-ci/typos@80c8a4945eec0f6d464eaf9e65ed98ef085283d1 # v1 clippy: runs-on: depot-ubuntu-latest - timeout-minutes: 5 + timeout-minutes: 30 permissions: contents: read steps: @@ -116,7 +116,7 @@ jobs: rustfmt: runs-on: depot-ubuntu-latest - timeout-minutes: 5 + timeout-minutes: 30 permissions: contents: read steps: @@ -131,7 +131,7 @@ jobs: forge-fmt: runs-on: depot-ubuntu-latest - timeout-minutes: 5 + timeout-minutes: 30 permissions: contents: read steps: @@ -149,7 +149,7 @@ jobs: crate-checks: runs-on: depot-ubuntu-latest - timeout-minutes: 5 + timeout-minutes: 30 permissions: contents: read steps: @@ -160,7 +160,7 @@ jobs: with: toolchain: stable - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 - - uses: taiki-e/install-action@e43a5023a747770bfcb71ae048541a681714b951 # v2 + - uses: taiki-e/install-action@e7ef886cf8f69c25ecef6bbc2858a42e273496ec # v2 with: tool: cargo-hack - uses: mozilla-actions/sccache-action@7d986dd989559c6ecdb630a3fd2557667be217ad # v0.0.9 @@ -214,7 +214,7 @@ jobs: - crate-checks - deny - codeql - timeout-minutes: 5 + timeout-minutes: 30 steps: - name: Decide whether the needed jobs succeeded or failed uses: re-actors/alls-green@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe # release/v1 From 243077e8a2bbc64b90416152d1ac221d05f19203 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Sun, 19 Oct 2025 01:51:58 +0700 Subject: [PATCH 106/232] Delete .circleci/ci.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .circleci/ci.yml | 31 ------------------------------- 1 file changed, 31 deletions(-) delete mode 100644 .circleci/ci.yml diff --git a/.circleci/ci.yml b/.circleci/ci.yml deleted file mode 100644 index f967cfaa30db5..0000000000000 --- a/.circleci/ci.yml +++ /dev/null @@ -1,31 +0,0 @@ -# Use the latest 2.1 version of CircleCI pipeline process engine. -# See: https://circleci.com/docs/reference/configuration-reference -version: 2.1 - -# Define a job to be invoked later in a workflow. -# See: https://circleci.com/docs/guides/orchestrate/jobs-steps/#jobs-overview & https://circleci.com/docs/reference/configuration-reference/#jobs -jobs: - say-hello: - # Specify the execution environment. You can specify an image from Docker Hub or use one of our convenience images from CircleCI's Developer Hub. - # See: https://circleci.com/docs/guides/execution-managed/executor-intro/ & https://circleci.com/docs/reference/configuration-reference/#executor-job - docker: - # Specify the version you desire here - # See: https://circleci.com/developer/images/image/cimg/base - - image: cimg/base:current - - # Add steps to the job - # See: https://circleci.com/docs/guides/orchestrate/jobs-steps/#steps-overview & https://circleci.com/docs/reference/configuration-reference/#steps - steps: - # Checkout the code as the first step. - - checkout - - run: - name: "Say hello" - command: "echo Hello, World!" - -# Orchestrate jobs using workflows -# See: https://circleci.com/docs/guides/orchestrate/workflows/ & https://circleci.com/docs/reference/configuration-reference/#workflows -workflows: - say-hello-workflow: # This is the name of the workflow, feel free to change it to better match your workflow. - # Inside the workflow, you define the jobs you want to run. - jobs: - - say-hello From 081909d7ec8c854adf4a34a5d7d1d18b294a93c6 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Sun, 19 Oct 2025 01:28:24 +0000 Subject: [PATCH 107/232] Update cargo.yml (#171) CI/CD Configuration Update: The CircleCI configuration file, cargo.yml, has been updated to use a newer version of the Rust Docker image. Rust Toolchain Version Bump: The cimg/rust Docker image version has been incremented from 1.88.0 to 1.89.0, ensuring the CI pipeline utilizes a more recent Rust toolchain. Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .circleci/cargo.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/cargo.yml b/.circleci/cargo.yml index 46a18d45a5fca..d7a82b5c93b6e 100644 --- a/.circleci/cargo.yml +++ b/.circleci/cargo.yml @@ -3,7 +3,7 @@ version: 2.1 jobs: build-and-test: docker: - - image: cimg/rust:1.88.0 + - image: cimg/rust:1.89.0 steps: - checkout - restore_cache: From 2c1f1f9ee1e9e894dc2df4ab4d18b8fa7b810596 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Sun, 19 Oct 2025 19:42:58 +0000 Subject: [PATCH 108/232] Delete .circleci/ci_v1.yml (#173) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --- .circleci/ci_v1.yml | 31 ------------------------------- 1 file changed, 31 deletions(-) delete mode 100644 .circleci/ci_v1.yml diff --git a/.circleci/ci_v1.yml b/.circleci/ci_v1.yml deleted file mode 100644 index 94bf46b3bb04f..0000000000000 --- a/.circleci/ci_v1.yml +++ /dev/null @@ -1,31 +0,0 @@ -version: 2.1 - -jobs: - build-and-test: - docker: - - image: cimg/rust:1.88.0 - steps: - - checkout - - restore_cache: - keys: - - v1-cargo-{{ checksum "Cargo.lock" }} - - v1-cargo- - - run: - name: "Check formatting" - command: cargo fmt -- --check - - run: - name: "Run tests" - command: cargo test - - save_cache: - key: v1-cargo-{{ checksum "Cargo.lock" }} - paths: - - "~/.cargo/bin" - - "~/.cargo/registry/index" - - "~/.cargo/registry/cache" - - "~/.cargo/git/db" - - "target" - -workflows: - ci: - jobs: - - build-and-test From b1d84b66b81a035c156dfd555df2e50cd4c4d8d6 Mon Sep 17 00:00:00 2001 From: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Date: Sun, 19 Oct 2025 20:06:59 +0000 Subject: [PATCH 109/232] Update cargo.yml (#174) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> From 7de78fb9fc7cead569c81669e74d36941b6bbd2f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Oct 2025 21:42:52 +0700 Subject: [PATCH 110/232] chore(deps): bump taiki-e/install-action from 2.62.28 to 2.62.33 (#175) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.62.28 to 2.62.33. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/v2.62.28...e43a5023a747770bfcb71ae048541a681714b951) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-version: 2.62.33 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 447e61f3a0afa..8a1ab60296d24 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -166,7 +166,7 @@ jobs: with: toolchain: stable - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 - - uses: taiki-e/install-action@e7ef886cf8f69c25ecef6bbc2858a42e273496ec # v2 + - uses: taiki-e/install-action@e43a5023a747770bfcb71ae048541a681714b951 # v2 with: tool: cargo-hack - uses: mozilla-actions/sccache-action@7d986dd989559c6ecdb630a3fd2557667be217ad # v0.0.9 From c56008ed7b73e17973d518036a2fb7117b0d9230 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Tue, 21 Oct 2025 14:17:06 +0000 Subject: [PATCH 111/232] Delete .circleci/cargo.yml (#179) I Configuration Removal: The .circleci/cargo.yml file, which defined CircleCI jobs for building and testing Rust projects, has been completely removed from the repository. Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- .circleci/cargo.yml | 37 ------------------------------------- 1 file changed, 37 deletions(-) delete mode 100644 .circleci/cargo.yml diff --git a/.circleci/cargo.yml b/.circleci/cargo.yml deleted file mode 100644 index d7a82b5c93b6e..0000000000000 --- a/.circleci/cargo.yml +++ /dev/null @@ -1,37 +0,0 @@ -version: 2.1 - -jobs: - build-and-test: - docker: - - image: cimg/rust:1.89.0 - steps: - - checkout - - restore_cache: - keys: - - v1-cargo-{{ checksum "Cargo.lock" }} - - v1-cargo- - - run: - name: "Check formatting" - command: cargo fmt -- --check - - run: - name: "Run tests" - command: cargo test - - save_cache: - key: v1-cargo-{{ checksum "Cargo.lock" }} - paths: - - "~/.cargo/bin" - - "~/.cargo/registry/index" - - "~/.cargo/registry/cache" - - "~/.cargo/git/db" - - "target" - - run: - name: "Check formatting" - command: cargo fmt -- --check - - run: - name: "Run tests" - command: cargo test - -workflows: - ci: - jobs: - - build-and-test From e3ae5bef386108acd6f65ec292468016c38213dc Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Tue, 21 Oct 2025 20:27:46 +0000 Subject: [PATCH 112/232] Delete .circleci/ci_v1.yml (#182) Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- .circleci/ci_v1.yml | 31 ------------------------------- 1 file changed, 31 deletions(-) delete mode 100644 .circleci/ci_v1.yml diff --git a/.circleci/ci_v1.yml b/.circleci/ci_v1.yml deleted file mode 100644 index 94bf46b3bb04f..0000000000000 --- a/.circleci/ci_v1.yml +++ /dev/null @@ -1,31 +0,0 @@ -version: 2.1 - -jobs: - build-and-test: - docker: - - image: cimg/rust:1.88.0 - steps: - - checkout - - restore_cache: - keys: - - v1-cargo-{{ checksum "Cargo.lock" }} - - v1-cargo- - - run: - name: "Check formatting" - command: cargo fmt -- --check - - run: - name: "Run tests" - command: cargo test - - save_cache: - key: v1-cargo-{{ checksum "Cargo.lock" }} - paths: - - "~/.cargo/bin" - - "~/.cargo/registry/index" - - "~/.cargo/registry/cache" - - "~/.cargo/git/db" - - "target" - -workflows: - ci: - jobs: - - build-and-test From 956581c9997b1f362083c74c91cb5d5d5de8fe44 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Tue, 21 Oct 2025 20:29:35 +0000 Subject: [PATCH 113/232] Update config.yml (#183) Configuration File Cleanup: Removed an unnecessary blank line in the .circleci/config.yml file, improving its formatting and readability. Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- .circleci/config.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index f967cfaa30db5..df6b1216062af 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,7 +1,6 @@ # Use the latest 2.1 version of CircleCI pipeline process engine. # See: https://circleci.com/docs/reference/configuration-reference version: 2.1 - # Define a job to be invoked later in a workflow. # See: https://circleci.com/docs/guides/orchestrate/jobs-steps/#jobs-overview & https://circleci.com/docs/reference/configuration-reference/#jobs jobs: From 0ba70d2cd676df26ef1bb1da45cdb0dbc22e05f0 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Tue, 21 Oct 2025 21:24:31 +0000 Subject: [PATCH 114/232] Update config.yml (#187) Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- .circleci/config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index df6b1216062af..1b131002534c9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,5 +1,6 @@ # Use the latest 2.1 version of CircleCI pipeline process engine. # See: https://circleci.com/docs/reference/configuration-reference + version: 2.1 # Define a job to be invoked later in a workflow. # See: https://circleci.com/docs/guides/orchestrate/jobs-steps/#jobs-overview & https://circleci.com/docs/reference/configuration-reference/#jobs From f6a1abeffd51ef2dd63204cfdba28c93c583cce4 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Wed, 22 Oct 2025 10:49:42 +0000 Subject: [PATCH 115/232] Delete .circleci/config.yml Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- .circleci/config.yml | 31 ------------------------------- 1 file changed, 31 deletions(-) delete mode 100644 .circleci/config.yml diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index f967cfaa30db5..0000000000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,31 +0,0 @@ -# Use the latest 2.1 version of CircleCI pipeline process engine. -# See: https://circleci.com/docs/reference/configuration-reference -version: 2.1 - -# Define a job to be invoked later in a workflow. -# See: https://circleci.com/docs/guides/orchestrate/jobs-steps/#jobs-overview & https://circleci.com/docs/reference/configuration-reference/#jobs -jobs: - say-hello: - # Specify the execution environment. You can specify an image from Docker Hub or use one of our convenience images from CircleCI's Developer Hub. - # See: https://circleci.com/docs/guides/execution-managed/executor-intro/ & https://circleci.com/docs/reference/configuration-reference/#executor-job - docker: - # Specify the version you desire here - # See: https://circleci.com/developer/images/image/cimg/base - - image: cimg/base:current - - # Add steps to the job - # See: https://circleci.com/docs/guides/orchestrate/jobs-steps/#steps-overview & https://circleci.com/docs/reference/configuration-reference/#steps - steps: - # Checkout the code as the first step. - - checkout - - run: - name: "Say hello" - command: "echo Hello, World!" - -# Orchestrate jobs using workflows -# See: https://circleci.com/docs/guides/orchestrate/workflows/ & https://circleci.com/docs/reference/configuration-reference/#workflows -workflows: - say-hello-workflow: # This is the name of the workflow, feel free to change it to better match your workflow. - # Inside the workflow, you define the jobs you want to run. - jobs: - - say-hello From 58865b9bc8090e4aa448653074372d36c36889ee Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Wed, 22 Oct 2025 19:50:32 +0700 Subject: [PATCH 116/232] Delete .circleci directory Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- .circleci/config.yml | 31 ------------------------------- 1 file changed, 31 deletions(-) delete mode 100644 .circleci/config.yml diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index 1b131002534c9..0000000000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,31 +0,0 @@ -# Use the latest 2.1 version of CircleCI pipeline process engine. -# See: https://circleci.com/docs/reference/configuration-reference - -version: 2.1 -# Define a job to be invoked later in a workflow. -# See: https://circleci.com/docs/guides/orchestrate/jobs-steps/#jobs-overview & https://circleci.com/docs/reference/configuration-reference/#jobs -jobs: - say-hello: - # Specify the execution environment. You can specify an image from Docker Hub or use one of our convenience images from CircleCI's Developer Hub. - # See: https://circleci.com/docs/guides/execution-managed/executor-intro/ & https://circleci.com/docs/reference/configuration-reference/#executor-job - docker: - # Specify the version you desire here - # See: https://circleci.com/developer/images/image/cimg/base - - image: cimg/base:current - - # Add steps to the job - # See: https://circleci.com/docs/guides/orchestrate/jobs-steps/#steps-overview & https://circleci.com/docs/reference/configuration-reference/#steps - steps: - # Checkout the code as the first step. - - checkout - - run: - name: "Say hello" - command: "echo Hello, World!" - -# Orchestrate jobs using workflows -# See: https://circleci.com/docs/guides/orchestrate/workflows/ & https://circleci.com/docs/reference/configuration-reference/#workflows -workflows: - say-hello-workflow: # This is the name of the workflow, feel free to change it to better match your workflow. - # Inside the workflow, you define the jobs you want to run. - jobs: - - say-hello From e060526516fb805f9d3be6c38bb99811c0c80447 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Wed, 22 Oct 2025 14:42:40 +0000 Subject: [PATCH 117/232] Update ci_v1.yml Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> From 6ff6e5954ec7ed348c745f2f4ab19d3bec7e2371 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Wed, 22 Oct 2025 14:43:12 +0000 Subject: [PATCH 118/232] Update Rust Docker image version to 1.89.0 Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- .circleci/ci_v1.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/ci_v1.yml b/.circleci/ci_v1.yml index 94bf46b3bb04f..82c6de5b42b73 100644 --- a/.circleci/ci_v1.yml +++ b/.circleci/ci_v1.yml @@ -3,7 +3,7 @@ version: 2.1 jobs: build-and-test: docker: - - image: cimg/rust:1.88.0 + - image: cimg/rust:1.89.0 steps: - checkout - restore_cache: From 1b37bfc8cc836fb459cf8a4dfa30ee9f2ec25a84 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Thu, 23 Oct 2025 17:04:59 +0700 Subject: [PATCH 119/232] Potential fix for code scanning alert no. 76: Artifact poisoning Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- .github/workflows/npm.yml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/npm.yml b/.github/workflows/npm.yml index 79f9c45604119..b410a80d7d11f 100644 --- a/.github/workflows/npm.yml +++ b/.github/workflows/npm.yml @@ -162,10 +162,11 @@ jobs: PLATFORM_NAME=${{ matrix.os }} ARCH=${{ matrix.arch }} FORGE_BIN_PATH="$BIN" bun ./scripts/prepublish.ts - name: Sanity Check Binary - working-directory: ./npm + env: + ARTIFACT_DIR: ${{ steps.paths.outputs.artifact_dir }} run: | set -euo pipefail - PKG_DIR="./@foundry-rs/forge-${{ matrix.os }}-${{ matrix.arch }}" + PKG_DIR="$ARTIFACT_DIR/@foundry-rs/forge-${{ matrix.os }}-${{ matrix.arch }}" BIN="$PKG_DIR/bin/forge" if [[ "${{ matrix.os }}" == "win32" ]]; then BIN="$PKG_DIR/bin/forge.exe" @@ -185,7 +186,7 @@ jobs: fi - name: Publish ${{ matrix.os }}-${{ matrix.arch }} Binary - working-directory: ./npm + ARTIFACT_DIR: ${{ steps.paths.outputs.artifact_dir }} env: PROVENANCE: true VERSION_NAME: ${{ steps.release-version.outputs.RELEASE_VERSION }} @@ -195,9 +196,9 @@ jobs: run: | set -euo pipefail - ls -la ./@foundry-rs/forge-${{ matrix.os }}-${{ matrix.arch }} + ls -la "$ARTIFACT_DIR/@foundry-rs/forge-${{ matrix.os }}-${{ matrix.arch }}" - bun ./scripts/publish.ts ./@foundry-rs/forge-${{ matrix.os }}-${{ matrix.arch }} + bun ./scripts/publish.ts "$ARTIFACT_DIR/@foundry-rs/forge-${{ matrix.os }}-${{ matrix.arch }}" echo "Published @foundry-rs/forge-${{ matrix.os }}-${{ matrix.arch }}" From 635d4360f35cecb84e4b3d72036fa63513c5b44a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Oct 2025 16:42:21 +0000 Subject: [PATCH 120/232] chore(deps): bump alloy-dyn-abi in the cargo group across 1 directory Bumps the cargo group with 1 update in the / directory: [alloy-dyn-abi](https://github.com/alloy-rs/core). Updates `alloy-dyn-abi` from 0.8.25 to 0.8.26 - [Release notes](https://github.com/alloy-rs/core/releases) - [Changelog](https://github.com/alloy-rs/core/blob/v0.8.26/CHANGELOG.md) - [Commits](https://github.com/alloy-rs/core/compare/v0.8.25...v0.8.26) --- updated-dependencies: - dependency-name: alloy-dyn-abi dependency-version: 0.8.26 dependency-type: direct:production dependency-group: cargo ... Signed-off-by: dependabot[bot] --- Cargo.lock | 88 ++++++++++++++++++++++++++++++++++-------------------- Cargo.toml | 2 +- 2 files changed, 57 insertions(+), 33 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e972d3906b5dc..830ba11d18833 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -130,16 +130,15 @@ dependencies = [ [[package]] name = "alloy-dyn-abi" -version = "1.1.2" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18cc14d832bc3331ca22a1c7819de1ede99f58f61a7d123952af7dde8de124a6" +checksum = "3fdff496dd4e98a81f4861e66f7eaf5f2488971848bb42d9c892f871730245c8" dependencies = [ "alloy-json-abi", "alloy-primitives", "alloy-sol-type-parser", "alloy-sol-types", "arbitrary", - "derive_arbitrary", "derive_more 2.0.1", "itoa", "proptest", @@ -286,9 +285,9 @@ dependencies = [ [[package]] name = "alloy-json-abi" -version = "1.1.2" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ccaa79753d7bf15f06399ea76922afbfaf8d18bebed9e8fc452984b4a90dcc9" +checksum = "5513d5e6bd1cba6bdcf5373470f559f320c05c8c59493b6e98912fbe6733943f" dependencies = [ "alloy-primitives", "alloy-sol-type-parser", @@ -378,20 +377,19 @@ dependencies = [ [[package]] name = "alloy-primitives" -version = "1.1.2" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18c35fc4b03ace65001676358ffbbaefe2a2b27ee50fe777c345082c7c888be8" +checksum = "355bf68a433e0fd7f7d33d5a9fc2583fde70bf5c530f63b80845f8da5505cf28" dependencies = [ "alloy-rlp", "arbitrary", "bytes", "cfg-if", "const-hex", - "derive_arbitrary", "derive_more 2.0.1", - "foldhash", + "foldhash 0.2.0", "getrandom 0.3.3", - "hashbrown 0.15.3", + "hashbrown 0.16.0", "indexmap 2.9.0", "itoa", "k256", @@ -769,9 +767,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro" -version = "1.1.2" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8612e0658964d616344f199ab251a49d48113992d81b92dab93ed855faa66383" +checksum = "f3ce480400051b5217f19d6e9a82d9010cdde20f1ae9c00d53591e4a1afbb312" dependencies = [ "alloy-sol-macro-expander", "alloy-sol-macro-input", @@ -783,9 +781,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro-expander" -version = "1.1.2" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a384edac7283bc4c010a355fb648082860c04b826bb7a814c45263c8f304c74" +checksum = "6d792e205ed3b72f795a8044c52877d2e6b6e9b1d13f431478121d8d4eaa9028" dependencies = [ "alloy-json-abi", "alloy-sol-macro-input", @@ -802,9 +800,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro-input" -version = "1.1.2" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd588c2d516da7deb421b8c166dc60b7ae31bca5beea29ab6621fcfa53d6ca5" +checksum = "0bd1247a8f90b465ef3f1207627547ec16940c35597875cdc09c49d58b19693c" dependencies = [ "alloy-json-abi", "const-hex", @@ -820,9 +818,9 @@ dependencies = [ [[package]] name = "alloy-sol-type-parser" -version = "1.1.2" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86ddeb70792c7ceaad23e57d52250107ebbb86733e52f4a25d8dc1abc931837" +checksum = "954d1b2533b9b2c7959652df3076954ecb1122a28cc740aa84e7b0a49f6ac0a9" dependencies = [ "serde", "winnow", @@ -830,9 +828,9 @@ dependencies = [ [[package]] name = "alloy-sol-types" -version = "1.1.2" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "584cb97bfc5746cb9dcc4def77da11694b5d6d7339be91b7480a6a68dc129387" +checksum = "70319350969a3af119da6fb3e9bddb1bce66c9ea933600cb297c8b1850ad2a3c" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -3803,6 +3801,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + [[package]] name = "forge" version = "1.2.1" @@ -5008,7 +5012,16 @@ checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3" dependencies = [ "allocator-api2", "equivalent", - "foldhash", + "foldhash 0.1.5", +] + +[[package]] +name = "hashbrown" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" +dependencies = [ + "foldhash 0.2.0", "serde", ] @@ -7138,9 +7151,9 @@ dependencies = [ [[package]] name = "proptest-derive" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ee1c9ac207483d5e7db4940700de86a9aae46ef90c48b57f99fe7edb8345e49" +checksum = "095a99f75c69734802359b682be8daaf8980296731f6470434ea2c652af1dd30" dependencies = [ "proc-macro2", "quote", @@ -7849,14 +7862,15 @@ dependencies = [ [[package]] name = "ruint" -version = "1.15.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11256b5fe8c68f56ac6f39ef0720e592f33d2367a4782740d9c9142e889c7fb4" +checksum = "a68df0380e5c9d20ce49534f292a36a7514ae21350726efe1865bdb1fa91d278" dependencies = [ "alloy-rlp", "arbitrary", "ark-ff 0.3.0", "ark-ff 0.4.2", + "ark-ff 0.5.0", "bytes", "fastrlp 0.3.1", "fastrlp 0.4.0", @@ -7870,7 +7884,7 @@ dependencies = [ "rand 0.9.1", "rlp", "ruint-macro", - "serde", + "serde_core", "valuable", "zeroize", ] @@ -8270,18 +8284,28 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", @@ -9068,9 +9092,9 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "1.1.2" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5d879005cc1b5ba4e18665be9e9501d9da3a9b95f625497c4cb7ee082b532e" +checksum = "ff790eb176cc81bb8936aed0f7b9f14fc4670069a2d371b3e3b0ecce908b2cb3" dependencies = [ "paste", "proc-macro2", diff --git a/Cargo.toml b/Cargo.toml index 76f51d5337151..68e6e2881ff7d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -232,7 +232,7 @@ alloy-transport-ipc = { version = "1.0.5", default-features = false } alloy-transport-ws = { version = "1.0.5", default-features = false } ## alloy-core -alloy-dyn-abi = "1.0" +alloy-dyn-abi = "1.4" alloy-json-abi = "1.0" alloy-primitives = { version = "1.0", features = [ "getrandom", From 14f26f52dbe20e3ad1e33723e6a492a7adf2fc76 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Thu, 23 Oct 2025 23:44:17 +0700 Subject: [PATCH 121/232] Create ci-web3-gamefi.yml Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- .circleci/ci-web3-gamefi.yml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 .circleci/ci-web3-gamefi.yml diff --git a/.circleci/ci-web3-gamefi.yml b/.circleci/ci-web3-gamefi.yml new file mode 100644 index 0000000000000..ad53a8e498202 --- /dev/null +++ b/.circleci/ci-web3-gamefi.yml @@ -0,0 +1,26 @@ +# Use the latest 2.1 version of CircleCI pipeline process engine. +# See: https://circleci.com/docs/configuration-reference + +version: 2.1 +executors: + my-custom-executor: + docker: + - image: cimg/base:stable + auth: + # ensure you have first added these secrets + # visit app.circleci.com/settings/project/github/Dargon789/foundry/environment-variables + username: $DOCKER_HUB_USER + password: $DOCKER_HUB_PASSWORD +jobs: + web3-defi-game-project-: + + executor: my-custom-executor + steps: + - checkout + - run: | + # echo Hello, World! + +workflows: + my-custom-workflow: + jobs: + - web3-defi-game-project- From b3bbd1ef5c91bbe27b1f3ba1c3f0886afd3316a8 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Fri, 24 Oct 2025 01:35:25 +0700 Subject: [PATCH 122/232] Potential fix for code scanning alert no. 74: Artifact poisoning Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- .github/workflows/npm.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.github/workflows/npm.yml b/.github/workflows/npm.yml index 79f9c45604119..60c1fe01c64e1 100644 --- a/.github/workflows/npm.yml +++ b/.github/workflows/npm.yml @@ -98,6 +98,17 @@ jobs: node-version: "24" registry-url: "https://registry.npmjs.org" + - name: Validate npm directory for artifact poisoning + run: | + set -euo pipefail + # Disallow dangerous files likely to be poisoned by artifacts + for f in "package.json" "bun.lockb" "package-lock.json" "yarn.lock" ".npmrc"; do + if [ -f "./npm/$f" ]; then + echo "ERROR: Untrusted '$f' present in ./npm – aborting to prevent artifact poisoning." + exit 1 + fi + done + - name: Install Dependencies working-directory: ./npm run: bun install --frozen-lockfile From e101ade3d5caa414dc80ef96f69740c17bf08790 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Fri, 24 Oct 2025 01:35:55 +0700 Subject: [PATCH 123/232] Potential fix for code scanning alert no. 83: Uncontrolled data used in path expression Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- benches/src/lib.rs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/benches/src/lib.rs b/benches/src/lib.rs index e123988861691..500eef320deef 100644 --- a/benches/src/lib.rs +++ b/benches/src/lib.rs @@ -130,10 +130,20 @@ impl BenchmarkProject { for entry in std::fs::read_dir(&root_path)? { let entry = entry?; let path = entry.path(); - if path.is_dir() { - std::fs::remove_dir_all(&path).ok(); + // Canonicalize the entry to prevent directory traversal + let canon = match path.canonicalize() { + Ok(p) => p, + Err(_) => continue, // Skip if unable to canonicalize + }; + // Ensure canonicalized path stays strictly within root_path (TempProject root) + if !canon.starts_with(&root_path) { + sh_eprintln!("⚠️ Skipping suspicious path during cleanup: {:?}", canon); + continue; + } + if canon.is_dir() { + std::fs::remove_dir_all(&canon).ok(); } else { - std::fs::remove_file(&path).ok(); + std::fs::remove_file(&canon).ok(); } } From d96b67de4b62a28833f79ae0211420616c8ed44d Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Fri, 24 Oct 2025 01:38:59 +0700 Subject: [PATCH 124/232] Potential fix for code scanning alert no. 93: Uncontrolled data used in path expression Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- crates/evm/evm/src/executors/corpus.rs | 33 ++++++++++++++++++++------ 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/crates/evm/evm/src/executors/corpus.rs b/crates/evm/evm/src/executors/corpus.rs index 4577c9788d708..e4de7932f55f4 100644 --- a/crates/evm/evm/src/executors/corpus.rs +++ b/crates/evm/evm/src/executors/corpus.rs @@ -190,6 +190,15 @@ impl CorpusManager { foundry_common::fs::create_dir_all(corpus_dir)?; } + // Canonicalize the corpus_dir to a trusted absolute path + let canonical_corpus_dir = match corpus_dir.canonicalize() { + Ok(dir) => dir, + Err(e) => { + trace!(target: "corpus", "failed to canonicalize corpus_dir {}: {e}", corpus_dir.display()); + return Err(e.into()); + } + }; + let can_replay_tx = |tx: &BasicTxDetails| -> bool { fuzzed_contracts.is_some_and(|contracts| contracts.targets.lock().can_replay(tx)) || fuzzed_function.is_some_and(|function| { @@ -202,21 +211,31 @@ impl CorpusManager { 'corpus_replay: for entry in std::fs::read_dir(corpus_dir)? { let path = entry?.path(); - if path.is_file() - && let Some(name) = path.file_name().and_then(|s| s.to_str()) + // Canonicalize the candidate path, skip if it cannot be canonicalized (e.g. broken symlink) + let canonical_path = match path.canonicalize() { + Ok(p) => p, + Err(_) => continue, + }; + // Ensure file is inside the corpus directory (prevents path traversal/symlink escape) + if !canonical_path.starts_with(&canonical_corpus_dir) { + trace!(target: "corpus", "Skipping file outside corpus_dir: {}", path.display()); + continue; + } + if canonical_path.is_file() + && let Some(name) = canonical_path.file_name().and_then(|s| s.to_str()) && name.contains(METADATA_SUFFIX) { // Ignore metadata files continue; } - let read_corpus_result = match path.extension().and_then(|ext| ext.to_str()) { - Some("gz") => foundry_common::fs::read_json_gzip_file::>(&path), - _ => foundry_common::fs::read_json_file::>(&path), + let read_corpus_result = match canonical_path.extension().and_then(|ext| ext.to_str()) { + Some("gz") => foundry_common::fs::read_json_gzip_file::>(&canonical_path), + _ => foundry_common::fs::read_json_file::>(&canonical_path), }; let Ok(tx_seq) = read_corpus_result else { - trace!(target: "corpus", "failed to load corpus from {}", path.display()); + trace!(target: "corpus", "failed to load corpus from {}", canonical_path.display()); continue; }; @@ -265,7 +284,7 @@ impl CorpusManager { ); // Populate in memory corpus with the sequence from corpus file. - in_memory_corpus.push(CorpusEntry::new(tx_seq, path)?); + in_memory_corpus.push(CorpusEntry::new(tx_seq, canonical_path.clone())?); } } From 3011ba593af52c4ce3ae1090d04d44d67b9d5ff9 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Fri, 24 Oct 2025 01:40:44 +0700 Subject: [PATCH 125/232] Potential fix for code scanning alert no. 76: Artifact poisoning Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- .github/workflows/npm.yml | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/.github/workflows/npm.yml b/.github/workflows/npm.yml index 60c1fe01c64e1..d20eb24129462 100644 --- a/.github/workflows/npm.yml +++ b/.github/workflows/npm.yml @@ -87,6 +87,37 @@ jobs: github-token: ${{ secrets.GITHUB_TOKEN }} run-id: ${{ github.event.workflow_run.id || inputs.run_id }} + - name: Validate and Copy Artifacts + env: + ARTIFACT_DIR: ${{ steps.paths.outputs.artifact_dir }} + run: | + set -euo pipefail + # List expected artifacts and their paths + EXPECTED_PATHS=( + "@foundry-rs/forge-linux-amd64" + "@foundry-rs/forge-linux-arm64" + "@foundry-rs/forge-darwin-amd64" + "@foundry-rs/forge-darwin-arm64" + "@foundry-rs/forge-win32-amd64" + ) + DEST_DIR="./npm" + mkdir -p "$DEST_DIR" + for PKG in "${EXPECTED_PATHS[@]}"; do + SRC="$ARTIFACT_DIR/$PKG" + if [ -d "$SRC" ]; then + echo "Validating and copying $SRC to $DEST_DIR" + # Optionally: validate files inside $SRC (e.g., hashes, signatures, expected file names) + # Basic check: ensure correct file structure + find "$SRC" -type f | grep -E '/bin/(forge|forge.exe)$' || { + echo "ERROR: Expected binary not found in $SRC" >&2 + exit 1 + } + cp -a "$SRC" "$DEST_DIR/" + else + echo "WARNING: Expected package $SRC not found in artifacts." + fi + done + ls -l "$DEST_DIR" - name: Setup Bun uses: oven-sh/setup-bun@735343b667d3e6f658f44d0eca948eb6282f2b76 # v2 with: @@ -196,6 +227,7 @@ jobs: fi - name: Publish ${{ matrix.os }}-${{ matrix.arch }} Binary + # Only use ./npm, which now contains validated/copies of artifact files working-directory: ./npm env: PROVENANCE: true From 321c2023ff954e2f0a99ad9d832ac2780dfaf872 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Fri, 24 Oct 2025 01:41:19 +0700 Subject: [PATCH 126/232] Potential fix for code scanning alert no. 94: Uncontrolled data used in path expression Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- crates/test-utils/src/script.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/crates/test-utils/src/script.rs b/crates/test-utils/src/script.rs index 839a3bfe8b224..e1f5d83e46408 100644 --- a/crates/test-utils/src/script.rs +++ b/crates/test-utils/src/script.rs @@ -123,6 +123,18 @@ impl ScriptTester { for entry in fs::read_dir(&from_dir)? { let file = &entry?.path(); let name = file.file_name().unwrap(); + // Validate file name to avoid path traversal and absolute paths + let name_str = name.to_string_lossy(); + if name_str.contains("..") || name_str.contains("/") || name_str.contains("\\") { + // Skip invalid (potentially dangerous) file names + continue; + } + // Optionally verify canonicalized file is in from_dir to avoid symlink traversal + if let Ok(canonical_file) = file.canonicalize() { + if !canonical_file.starts_with(&from_dir) { + continue; + } + } fs::copy(file, to_dir.join(name))?; } Ok(()) From 1bc0b5d5dd1ecfe05681f3b06e8faadc0c0a3ab5 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Fri, 24 Oct 2025 01:41:54 +0700 Subject: [PATCH 127/232] Potential fix for code scanning alert no. 80: Server-side request forgery Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- npm/src/const.ts | 25 ++++++++++++++++++++++++- npm/src/install.ts | 2 +- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/npm/src/const.ts b/npm/src/const.ts index 6762a149de196..1f0e32ab5d4fb 100644 --- a/npm/src/const.ts +++ b/npm/src/const.ts @@ -1,13 +1,36 @@ import type * as Process from 'node:process' + +// Allow-list of recognized/approved registry hostnames +export const ALLOWED_REGISTRY_HOSTS = [ + 'registry.npmjs.org', + 'localhost', + '127.0.0.1', + '::1', + // Add any additional trusted registry hosts below as needed +] + export function getRegistryUrl() { // Prefer npm's configured registry (works with Verdaccio and custom registries) // Fallback to REGISTRY_URL for tests/dev, then npmjs - return ( + const rawUrl = ( process.env.npm_config_registry || process.env.REGISTRY_URL || 'https://registry.npmjs.org' ) + let hostname + try { + hostname = new URL(rawUrl).hostname + } catch { + throw new Error(`Invalid registry URL: ${rawUrl}`) + } + if (!ALLOWED_REGISTRY_HOSTS.includes(hostname)) { + throw new Error( + `Registry URL host "${hostname}" is not in the allow-list (${ALLOWED_REGISTRY_HOSTS.join(', ')}). ` + + 'Set your registry to a trusted host.' + ) + } + return rawUrl } export type Architecture = Extract<(typeof Process)['arch'], 'arm64' | 'x64'> diff --git a/npm/src/install.ts b/npm/src/install.ts index a89fe5403571c..f637106a3e452 100644 --- a/npm/src/install.ts +++ b/npm/src/install.ts @@ -1,4 +1,4 @@ -import { BINARY_NAME, colors, getRegistryUrl, PLATFORM_SPECIFIC_PACKAGE_NAME } from '#const.ts' +import { BINARY_NAME, colors, getRegistryUrl, PLATFORM_SPECIFIC_PACKAGE_NAME, ALLOWED_REGISTRY_HOSTS } from '#const.ts' import * as NodeCrypto from 'node:crypto' import * as NodeFS from 'node:fs' import * as NodeHttp from 'node:http' From a970332c912f39c25246465f75ae4fb81a5e9bed Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Fri, 24 Oct 2025 15:42:45 +0700 Subject: [PATCH 128/232] Potential fix for code scanning alert no. 80: Server-side request forgery Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- npm/src/const.ts | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/npm/src/const.ts b/npm/src/const.ts index 6762a149de196..42a352712c6ba 100644 --- a/npm/src/const.ts +++ b/npm/src/const.ts @@ -1,13 +1,34 @@ import type * as Process from 'node:process' +const ALLOWED_REGISTRY_HOSTS = [ + 'registry.npmjs.org', + 'registry.yarnpkg.com', + // Add any additional trusted registry domains here +] + +function isAllowedRegistryHostname(urlString: string): boolean { + try { + const url = new URL(urlString) + // Compare against allow-list. Consider only exact domain match for safety. + return ALLOWED_REGISTRY_HOSTS.includes(url.hostname) + } catch { + return false + } +} + export function getRegistryUrl() { // Prefer npm's configured registry (works with Verdaccio and custom registries) // Fallback to REGISTRY_URL for tests/dev, then npmjs - return ( + const candidate = process.env.npm_config_registry || process.env.REGISTRY_URL || 'https://registry.npmjs.org' - ) + if (!isAllowedRegistryHostname(candidate)) { + throw new Error( + `Refusing to use registry URL '${candidate}' not in allowed list: ${ALLOWED_REGISTRY_HOSTS.join(', ')}` + ) + } + return candidate } export type Architecture = Extract<(typeof Process)['arch'], 'arm64' | 'x64'> From 1cf6991bb1b82fd10018efbe4ddbb31c001b9010 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Fri, 24 Oct 2025 09:24:29 +0000 Subject: [PATCH 129/232] Create codeql.yml (#208) --- .github/workflows/codeql.yml | 105 +++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 .github/workflows/codeql.yml diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000000000..63c774765c2b6 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,105 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL Advanced" + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + schedule: + - cron: '35 4 * * 6' + +jobs: + analyze: + name: Analyze (${{ matrix.language }}) + # Runner size impacts CodeQL analysis time. To learn more, please see: + # - https://gh.io/recommended-hardware-resources-for-running-codeql + # - https://gh.io/supported-runners-and-hardware-resources + # - https://gh.io/using-larger-runners (GitHub.com only) + # Consider using larger runners or machines with greater resources for possible analysis time improvements. + runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} + permissions: + # required for all workflows + security-events: write + + # required to fetch internal or private CodeQL packs + packages: read + + # only required for workflows in private repositories + actions: read + contents: read + + strategy: + fail-fast: false + matrix: + include: + - language: actions + build-mode: none + - language: javascript-typescript + build-mode: none + - language: python + build-mode: none + - language: rust + build-mode: none + # CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'rust', 'swift' + # Use `c-cpp` to analyze code written in C, C++ or both + # Use 'java-kotlin' to analyze code written in Java, Kotlin or both + # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both + # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis, + # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning. + # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how + # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + # Add any setup steps before running the `github/codeql-action/init` action. + # This includes steps like installing compilers or runtimes (`actions/setup-node` + # or others). This is typically only required for manual builds. + # - name: Setup runtime (example) + # uses: actions/setup-example@v1 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v4 + with: + languages: ${{ matrix.language }} + build-mode: ${{ matrix.build-mode }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + + # If the analyze step fails for one of the languages you are analyzing with + # "We were unable to automatically build your code", modify the matrix above + # to set the build mode to "manual" for that language. Then modify this step + # to build your code. + # ℹ️ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + - name: Run manual build steps + if: matrix.build-mode == 'manual' + shell: bash + run: | + echo 'If you are using a "manual" build mode for one or more of the' \ + 'languages you are analyzing, replace this with the commands to build' \ + 'your code, for example:' + echo ' make bootstrap' + echo ' make release' + exit 1 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v4 + with: + category: "/language:${{matrix.language}}" From 51d92e156cc3e15a605ebc08307d607f1b122fbe Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Fri, 24 Oct 2025 10:16:27 +0000 Subject: [PATCH 130/232] Update ci.yml (#209) Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --------- https://github.com/apps/gemini-code-assist Code Review This pull request updates the Rust version in the CI from 1.88.0 to 1.89.0. While this is a good maintenance step, I've identified a potential improvement for your CI configuration. The project's Cargo.toml specifies a Minimum Supported Rust Version (MSRV) of 1.86, but the CI doesn't test against it. I've added a comment suggesting the addition of an MSRV check to prevent compatibility issues. --- .circleci/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/ci.yml b/.circleci/ci.yml index 7293433a50f2d..e5e4c033b1e82 100644 --- a/.circleci/ci.yml +++ b/.circleci/ci.yml @@ -3,7 +3,7 @@ version: 2.1 jobs: build-and-test: docker: - - image: cimg/rust:1.88.0 + - image: cimg/rust:1.89.0 steps: - checkout - restore_cache: From ce554bee23a64865b45c5321dd4afef99d10e1d6 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Fri, 24 Oct 2025 10:58:37 +0000 Subject: [PATCH 131/232] Update cargo.yml (#210) https://github.com/apps/gemini-code-assist ------------------- Code Review This pull request downgrades the Rust version in the CI pipeline from 1.88.0 to 1.87.0. This is inconsistent with the project's declared Minimum Supported Rust Version (MSRV) of 1.89 in Cargo.toml. My review highlights this discrepancy and suggests aligning the CI's Rust version with the MSRV to ensure the project's compatibility guarantees are properly tested. --------------- Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- .circleci/cargo.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/cargo.yml b/.circleci/cargo.yml index 46a18d45a5fca..a8a81c7bbd986 100644 --- a/.circleci/cargo.yml +++ b/.circleci/cargo.yml @@ -3,7 +3,7 @@ version: 2.1 jobs: build-and-test: docker: - - image: cimg/rust:1.88.0 + - image: cimg/rust:1.87.0 steps: - checkout - restore_cache: From 647b198634605b36717e132d68c8c4ecdfc4fa9b Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Sun, 26 Oct 2025 04:55:38 +0000 Subject: [PATCH 132/232] Foundry rs maste 1f4b36a (#214) * Create jekyll.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Create docker-image.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 58: Workflow does not contain permissions Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Update .github/workflows/docker-image.yml Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Update docker-image.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Revert "chore: fix isolate tests (#10344)" This reverts commit 70ded2b35f95ee9b4ee94f5e44961914d30a87f7. * Delete .github/workflows/jekyll.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 19: Workflow does not contain permissions Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --------- Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 145 +++++++++++++--------------------- 1 file changed, 55 insertions(+), 90 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 06061ff6c7508..1b18d4ad1dd2c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,7 +1,5 @@ name: release -permissions: {} - on: push: tags: @@ -17,35 +15,31 @@ env: CARGO_TERM_COLOR: always IS_NIGHTLY: ${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' }} PROFILE: maxperf - STABLE_VERSION: "v1.3.6" + STABLE_VERSION: "v1.1.0" jobs: prepare: name: Prepare release runs-on: ubuntu-latest timeout-minutes: 30 - permissions: - contents: write - pull-requests: read outputs: tag_name: ${{ steps.release_info.outputs.tag_name }} release_name: ${{ steps.release_info.outputs.release_name }} changelog: ${{ steps.build_changelog.outputs.changelog }} steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v4 with: - persist-credentials: false fetch-depth: 0 - name: Compute release name and tag id: release_info run: | if [[ ${IS_NIGHTLY} == 'true' ]]; then - printf 'tag_name=%s\n' "nightly-${GITHUB_SHA}" >> "$GITHUB_OUTPUT" - printf 'release_name=%s\n' "Nightly ($(date '+%Y-%m-%d'))" >> "$GITHUB_OUTPUT" + echo "tag_name=nightly-${GITHUB_SHA}" >> $GITHUB_OUTPUT + echo "release_name=Nightly ($(date '+%Y-%m-%d'))" >> $GITHUB_OUTPUT else - printf 'tag_name=%s\n' "$GITHUB_REF_NAME" >> "$GITHUB_OUTPUT" - printf 'release_name=%s\n' "$GITHUB_REF_NAME" >> "$GITHUB_OUTPUT" + echo "tag_name=${GITHUB_REF_NAME}" >> $GITHUB_OUTPUT + echo "release_name=${GITHUB_REF_NAME}" >> $GITHUB_OUTPUT fi # Creates a `nightly-SHA` tag for this specific nightly @@ -54,7 +48,7 @@ jobs: # the changelog. - name: Create build-specific nightly tag if: ${{ env.IS_NIGHTLY == 'true' }} - uses: actions/github-script@v8 + uses: actions/github-script@v7 env: TAG_NAME: ${{ steps.release_info.outputs.tag_name }} with: @@ -64,7 +58,7 @@ jobs: - name: Build changelog id: build_changelog - uses: mikepenz/release-changelog-builder-action@d702b5bb7c23735c8afc130dac9c4c8b8eb669e8 # v6 + uses: mikepenz/release-changelog-builder-action@v4 with: configuration: "./.github/changelog.json" fromTag: ${{ env.IS_NIGHTLY == 'true' && 'nightly' || env.STABLE_VERSION }} @@ -76,10 +70,6 @@ jobs: name: Release Docker needs: prepare uses: ./.github/workflows/docker-publish.yml - permissions: - contents: read - id-token: write - packages: write with: tag_name: ${{ needs.prepare.outputs.tag_name }} @@ -100,27 +90,28 @@ jobs: # `target`: Rust build target triple # `platform` and `arch`: Used in tarball names # `svm`: target platform to use for the Solc binary: https://github.com/roynalnaruto/svm-rs/blob/84cbe0ac705becabdc13168bae28a45ad2299749/svm-builds/build.rs#L4-L24 - # These are pinned to the oldest runner versions to support old libc/SDK versions. - - runner: depot-ubuntu-22.04-16 + - runner: Linux-22.04 target: x86_64-unknown-linux-gnu svm_target_platform: linux-amd64 platform: linux arch: amd64 - - runner: depot-ubuntu-22.04-16 + - runner: Linux-22.04 target: x86_64-unknown-linux-musl svm_target_platform: linux-amd64 platform: alpine arch: amd64 - - runner: depot-ubuntu-22.04-arm-16 + - runner: Linux-22.04 target: aarch64-unknown-linux-gnu svm_target_platform: linux-aarch64 platform: linux arch: arm64 - - runner: depot-ubuntu-22.04-16 + - runner: Linux-22.04 target: aarch64-unknown-linux-musl svm_target_platform: linux-aarch64 platform: alpine arch: arm64 + # This is pinned to `macos-13-large` to support old SDK versions. + # If the runner is deprecated it should be pinned to the oldest available version of the runner. - runner: macos-13-large target: x86_64-apple-darwin svm_target_platform: macosx-amd64 @@ -131,31 +122,31 @@ jobs: svm_target_platform: macosx-aarch64 platform: darwin arch: arm64 - - runner: depot-windows-latest-16 + - runner: Windows target: x86_64-pc-windows-msvc svm_target_platform: windows-amd64 platform: win32 arch: amd64 steps: - - uses: actions/checkout@v5 - with: - persist-credentials: false - - uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 # master + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable with: - toolchain: stable targets: ${{ matrix.target }} - - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 + - uses: Swatinem/rust-cache@v2 + with: + key: ${{ matrix.target }} + cache-on-failure: true - name: Apple M1 setup if: matrix.target == 'aarch64-apple-darwin' run: | - printf 'SDKROOT=%s\n' "$(xcrun -sdk macosx --show-sdk-path)" >> "$GITHUB_ENV" - printf 'MACOSX_DEPLOYMENT_TARGET=%s\n' "$(xcrun -sdk macosx --show-sdk-platform-version)" >> "$GITHUB_ENV" + echo "SDKROOT=$(xcrun -sdk macosx --show-sdk-path)" >> $GITHUB_ENV + echo "MACOSX_DEPLOYMENT_TARGET=$(xcrun -sdk macosx --show-sdk-platform-version)" >> $GITHUB_ENV - name: cross setup - if: contains(matrix.target, 'musl') + if: matrix.target == 'x86_64-unknown-linux-musl' || matrix.target == 'aarch64-unknown-linux-musl' || matrix.target == 'aarch64-unknown-linux-gnu' run: | - cargo install cross --git https://github.com/cross-rs/cross --rev baf457efc2555225af47963475bd70e8d2f5993f + cargo install cross - name: Build binaries env: @@ -167,8 +158,8 @@ jobs: shell: bash run: | set -eo pipefail - flags=(--target $TARGET --profile $PROFILE --bins - --no-default-features --features aws-kms,gcp-kms,cli,asm-keccak,js-tracer) + flags=(--target $TARGET --profile $PROFILE --bins + --no-default-features --features aws-kms,gcp-kms,cli,asm-keccak) # `jemalloc` is not fully supported on MSVC or aarch64 Linux. if [[ "$TARGET" != *msvc* && "$TARGET" != "aarch64-unknown-linux-gnu" ]]; then @@ -177,7 +168,7 @@ jobs: [[ "$TARGET" == *windows* ]] && ext=".exe" - if [[ "$TARGET" == *-musl ]]; then + if [[ "$TARGET" == *-musl || "$TARGET" == "aarch64-unknown-linux-gnu" ]]; then cross build "${flags[@]}" else cargo build "${flags[@]}" @@ -185,13 +176,13 @@ jobs: bins=(anvil cast chisel forge) for name in "${bins[@]}"; do - bin="$OUT_DIR/$name$ext" - printf '\n' + bin=$OUT_DIR/$name$ext + echo "" file "$bin" || true du -h "$bin" || true ldd "$bin" || true $bin --version || true - printf '%s_bin_path=%s\n' "$name" "$bin" >> "$GITHUB_ENV" + echo "${name}_bin_path=${bin}" >> $GITHUB_ENV done - name: Archive binaries @@ -204,27 +195,19 @@ jobs: shell: bash run: | if [[ "$PLATFORM_NAME" == "linux" || "$PLATFORM_NAME" == "alpine" ]]; then - tar -czvf "foundry_${VERSION_NAME}_${PLATFORM_NAME}_${ARCH}.tar.gz" -C "$OUT_DIR" forge cast anvil chisel - printf "file_name=%s\n" "foundry_${VERSION_NAME}_${PLATFORM_NAME}_${ARCH}.tar.gz" >> "$GITHUB_OUTPUT" + tar -czvf "foundry_${VERSION_NAME}_${PLATFORM_NAME}_${ARCH}.tar.gz" -C $OUT_DIR forge cast anvil chisel + echo "file_name=foundry_${VERSION_NAME}_${PLATFORM_NAME}_${ARCH}.tar.gz" >> $GITHUB_OUTPUT elif [ "$PLATFORM_NAME" == "darwin" ]; then # We need to use gtar here otherwise the archive is corrupt. # See: https://github.com/actions/virtual-environments/issues/2619 - gtar -czvf "foundry_${VERSION_NAME}_${PLATFORM_NAME}_${ARCH}.tar.gz" -C "$OUT_DIR" forge cast anvil chisel - printf "file_name=%s\n" "foundry_${VERSION_NAME}_${PLATFORM_NAME}_${ARCH}.tar.gz" >> "$GITHUB_OUTPUT" + gtar -czvf "foundry_${VERSION_NAME}_${PLATFORM_NAME}_${ARCH}.tar.gz" -C $OUT_DIR forge cast anvil chisel + echo "file_name=foundry_${VERSION_NAME}_${PLATFORM_NAME}_${ARCH}.tar.gz" >> $GITHUB_OUTPUT else - cd "$OUT_DIR" + cd $OUT_DIR 7z a -tzip "foundry_${VERSION_NAME}_${PLATFORM_NAME}_${ARCH}.zip" forge.exe cast.exe anvil.exe chisel.exe mv "foundry_${VERSION_NAME}_${PLATFORM_NAME}_${ARCH}.zip" ../../../ - printf "file_name=%s\n" "foundry_${VERSION_NAME}_${PLATFORM_NAME}_${ARCH}.zip" >> "$GITHUB_OUTPUT" + echo "file_name=foundry_${VERSION_NAME}_${PLATFORM_NAME}_${ARCH}.zip" >> $GITHUB_OUTPUT fi - printf "foundry_attestation=%s\n" "foundry_${VERSION_NAME}_${PLATFORM_NAME}_${ARCH}.attestation.txt" >> "$GITHUB_OUTPUT" - - - name: Upload build artifacts - uses: actions/upload-artifact@v4 - with: - retention-days: 1 - name: ${{ steps.artifacts.outputs.file_name }} - path: ${{ steps.artifacts.outputs.file_name }} - name: Build man page id: man @@ -244,30 +227,11 @@ jobs: gzip anvil.1 gzip chisel.1 tar -czvf "foundry_man_${VERSION_NAME}.tar.gz" forge.1.gz cast.1.gz anvil.1.gz chisel.1.gz - printf 'foundry_man=%s\n' "foundry_man_${VERSION_NAME}.tar.gz" >> "$GITHUB_OUTPUT" - - - name: Binaries attestation - id: attestation - uses: actions/attest-build-provenance@v3 - with: - subject-path: | - ${{ env.anvil_bin_path }} - ${{ env.cast_bin_path }} - ${{ env.chisel_bin_path }} - ${{ env.forge_bin_path }} - - - name: Record attestation URL - env: - ATTESTATION_URL: ${{ steps.attestation.outputs.attestation-url }} - FOUNDRY_ATTESTATION: ${{ steps.artifacts.outputs.foundry_attestation }} - shell: bash - run: | - set -euo pipefail - printf '%s\n' "$ATTESTATION_URL" > "$FOUNDRY_ATTESTATION" + echo "foundry_man=foundry_man_${VERSION_NAME}.tar.gz" >> $GITHUB_OUTPUT # Creates the release for this specific version - name: Create release - uses: softprops/action-gh-release@6da8fa9354ddfdc4aeace5fc48d7f679b5214090 # v2.4.1 + uses: softprops/action-gh-release@v2 with: name: ${{ needs.prepare.outputs.release_name }} tag_name: ${{ needs.prepare.outputs.tag_name }} @@ -275,14 +239,22 @@ jobs: body: ${{ needs.prepare.outputs.changelog }} files: | ${{ steps.artifacts.outputs.file_name }} - ${{ steps.artifacts.outputs.foundry_attestation }} ${{ steps.man.outputs.foundry_man }} + - name: Binaries attestation + uses: actions/attest-build-provenance@v2 + with: + subject-path: | + ${{ env.anvil_bin_path }} + ${{ env.cast_bin_path }} + ${{ env.chisel_bin_path }} + ${{ env.forge_bin_path }} + # If this is a nightly release, it also updates the release # tagged `nightly` for compatibility with `foundryup` - name: Update nightly release if: ${{ env.IS_NIGHTLY == 'true' }} - uses: softprops/action-gh-release@6da8fa9354ddfdc4aeace5fc48d7f679b5214090 # v2.4.1 + uses: softprops/action-gh-release@v2 with: name: "Nightly" tag_name: "nightly" @@ -290,33 +262,28 @@ jobs: body: ${{ needs.prepare.outputs.changelog }} files: | ${{ steps.artifacts.outputs.file_name }} - ${{ steps.artifacts.outputs.foundry_attestation }} ${{ steps.man.outputs.foundry_man }} cleanup: name: Release cleanup runs-on: ubuntu-latest timeout-minutes: 30 - permissions: - contents: write needs: release if: always() steps: - - uses: actions/checkout@v5 - with: - persist-credentials: false + - uses: actions/checkout@v4 # Moves the `nightly` tag to `HEAD` - name: Move nightly tag if: ${{ env.IS_NIGHTLY == 'true' }} - uses: actions/github-script@v8 + uses: actions/github-script@v7 with: script: | const moveTag = require('./.github/scripts/move-tag.js') await moveTag({ github, context }, 'nightly') - name: Delete old nightlies - uses: actions/github-script@v8 + uses: actions/github-script@v7 with: script: | const prunePrereleases = require('./.github/scripts/prune-prereleases.js') @@ -329,13 +296,11 @@ jobs: needs: [prepare, release-docker, release, cleanup] if: failure() permissions: - contents: read issues: write + contents: read steps: - - uses: actions/checkout@v5 - with: - persist-credentials: false - - uses: JasonEtco/create-an-issue@1b14a70e4d8dc185e5cc76d3bec9eab20257b2c5 # v2 + - uses: actions/checkout@v4 + - uses: JasonEtco/create-an-issue@v2 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} WORKFLOW_URL: | From 99d05916a91fc18c65bd20a60e585ace627d72c9 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Sun, 26 Oct 2025 15:23:58 +0000 Subject: [PATCH 133/232] Update and rename docker-image.yml to docker.yml (#218) Streamline the Docker CI workflow by renaming the file and enhancing it with scheduled runs, Buildx multi-platform builds, metadata tagging, conditional pushes, and automated image signing with Cosign. CI: Rename and replace the legacy docker-image.yml workflow with docker.yml Add scheduled cron runs and triggers on pushes to master, semver tags, and PRs Configure Docker Buildx for multi-platform builds with cache Extract Docker metadata and conditionally push images to GHCR on non-PR events Install Cosign and sign published Docker images using ephemeral identity tokens Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- .github/workflows/docker-image.yml | 21 ------ .github/workflows/docker.yml | 100 +++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+), 21 deletions(-) delete mode 100644 .github/workflows/docker-image.yml create mode 100644 .github/workflows/docker.yml diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml deleted file mode 100644 index e0c9c518e8748..0000000000000 --- a/.github/workflows/docker-image.yml +++ /dev/null @@ -1,21 +0,0 @@ -name: Docker Image CI - -on: - push: - branches: [ "master" ] - pull_request: - branches: [ "master" ] - -permissions: - contents: read - -jobs: - - build: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - name: Build the Docker image - run: docker build . --file Dockerfile --tag my-image-name:${{ github.sha }} diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 0000000000000..e994f94e7085c --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,100 @@ +name: Docker + +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +on: + schedule: + - cron: '21 12 * * *' + push: + branches: [ "master" ] + # Publish semver tags as releases. + tags: [ 'v*.*.*' ] + pull_request: + branches: [ "master" ] + +env: + # Use docker.io for Docker Hub if empty + REGISTRY: ghcr.io + # github.repository as / + IMAGE_NAME: ${{ github.repository }} + + +jobs: + build: + - name: Build the Docker image + run: docker build . --file path/to/Dockerfile --tag my-image-name:$(date +%s) + + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + # This is used to complete the identity challenge + # with sigstore/fulcio when running outside of PRs. + id-token: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + # Install the cosign tool except on PR + # https://github.com/sigstore/cosign-installer + - name: Install cosign + if: github.event_name != 'pull_request' + uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 #v3.5.0 + with: + cosign-release: 'v2.2.4' + + # Set up BuildKit Docker container builder to be able to build + # multi-platform images and export cache + # https://github.com/docker/setup-buildx-action + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0 + + # Login against a Docker registry except on PR + # https://github.com/docker/login-action + - name: Log into registry ${{ env.REGISTRY }} + if: github.event_name != 'pull_request' + uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + # Extract metadata (tags, labels) for Docker + # https://github.com/docker/metadata-action + - name: Extract Docker metadata + id: meta + uses: docker/metadata-action@96383f45573cb7f253c731d3b3ab81c87ef81934 # v5.0.0 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + + # Build and push Docker image with Buildx (don't push on PR) + # https://github.com/docker/build-push-action + - name: Build and push Docker image + id: build-and-push + uses: docker/build-push-action@v5.0.0 + with: + context: ./ + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max + + # Sign the resulting Docker image digest except on PRs. + # This will only write to the public Rekor transparency log when the Docker + # repository is public to avoid leaking data. If you would like to publish + # transparency data even for private images, pass --force to cosign below. + # https://github.com/sigstore/cosign + - name: Sign the published Docker image + if: ${{ github.event_name != 'pull_request' }} + env: + # https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-an-intermediate-environment-variable + TAGS: ${{ steps.meta.outputs.tags }} + DIGEST: ${{ steps.build-and-push.outputs.digest }} + # This step uses the identity token to provision an ephemeral certificate + # against the sigstore community Fulcio instance. + run: echo "${TAGS}" | xargs -I {} cosign sign --yes {}@${DIGEST} From ee6ba459e054c412b1aa90cf1975c33284b2476e Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Wed, 29 Oct 2025 21:29:14 +0700 Subject: [PATCH 134/232] Update ci.yml Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- .circleci/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/ci.yml b/.circleci/ci.yml index 7293433a50f2d..0d184dfcdec13 100644 --- a/.circleci/ci.yml +++ b/.circleci/ci.yml @@ -1,5 +1,5 @@ version: 2.1 - +# jobs: build-and-test: docker: From 4a51626d2317289955d6bbd82bed064074a87991 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Fri, 31 Oct 2025 07:50:14 +0700 Subject: [PATCH 135/232] Create docker-image.yml (#224) CI: Introduce docker-image.yml GitHub Actions workflow to checkout code and build Docker image on ubuntu-latest Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- .github/workflows/docker-image.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 .github/workflows/docker-image.yml diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml new file mode 100644 index 0000000000000..e0c9c518e8748 --- /dev/null +++ b/.github/workflows/docker-image.yml @@ -0,0 +1,21 @@ +name: Docker Image CI + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + +permissions: + contents: read + +jobs: + + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Build the Docker image + run: docker build . --file Dockerfile --tag my-image-name:${{ github.sha }} From f4ae42a12d4f5119710877ea3c5830578e6d744b Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Fri, 31 Oct 2025 10:37:07 +0700 Subject: [PATCH 136/232] Update config.yml (#225) CI: Insert comment lines to delineate and structure sections in .circleci/config.yml for enhanced clarity Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- .circleci/config.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 76b2889f1c4b2..a622410e8211b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,7 +1,7 @@ # Use the latest 2.1 version of CircleCI pipeline process engine. # See: https://circleci.com/docs/configuration-reference version: 2.1 - +# # Define a job to be invoked later in a workflow. # See: https://circleci.com/docs/jobs-steps/#jobs-overview & https://circleci.com/docs/configuration-reference/#jobs jobs: @@ -12,7 +12,7 @@ jobs: # Specify the version you desire here # See: https://circleci.com/developer/images/image/cimg/base - image: cimg/base:current - + # # Add steps to the job # See: https://circleci.com/docs/jobs-steps/#steps-overview & https://circleci.com/docs/configuration-reference/#steps steps: @@ -21,7 +21,7 @@ jobs: - run: name: "Say hello" command: "echo Hello, World!" - +# # Orchestrate jobs using workflows # See: https://circleci.com/docs/workflows/ & https://circleci.com/docs/configuration-reference/#workflows workflows: From 64546a91d35ddaeac83810303e006cd18928d21a Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Fri, 31 Oct 2025 11:39:16 +0700 Subject: [PATCH 137/232] Update sequence.rs (#226) Enhancements: Add standalone # lines in sequence.rs to serve as hidden placeholders for rustdoc examples Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- crates/script-sequence/src/sequence.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/script-sequence/src/sequence.rs b/crates/script-sequence/src/sequence.rs index 5759e7cf15208..143f6b3e9e8a1 100644 --- a/crates/script-sequence/src/sequence.rs +++ b/crates/script-sequence/src/sequence.rs @@ -12,7 +12,7 @@ use std::{ path::PathBuf, time::{Duration, SystemTime, UNIX_EPOCH}, }; - +# pub const DRY_RUN_DIR: &str = "dry-run"; #[derive(Clone, Serialize, Deserialize)] @@ -20,7 +20,7 @@ pub struct NestedValue { pub internal_type: String, pub value: String, } - +# /// Helper that saves the transactions sequence and its state on which transactions have been /// broadcasted #[derive(Clone, Default, Serialize, Deserialize)] @@ -148,7 +148,7 @@ impl ScriptSequence { pub fn add_receipt(&mut self, receipt: AnyTransactionReceipt) { self.receipts.push(receipt); } - + # /// Sorts all receipts with ascending transaction index pub fn sort_receipts(&mut self) { self.receipts.sort_by_key(|r| (r.block_number, r.transaction_index)); @@ -164,7 +164,7 @@ impl ScriptSequence { pub fn remove_pending(&mut self, tx_hash: TxHash) { self.pending.retain(|element| element != &tx_hash); } - + # /// Gets paths in the formats /// `./broadcast/[contract_filename]/[chain_id]/[sig]-[timestamp].json` and /// `./cache/[contract_filename]/[chain_id]/[sig]-[timestamp].json`. @@ -218,7 +218,7 @@ impl ScriptSequence { .for_each(|(i, tx)| tx.rpc.clone_from(&sensitive.transactions[i].rpc)); } } - +# /// Converts the `sig` argument into the corresponding file path. /// /// This accepts either the signature of the function or the raw calldata. From ecfc99bf2353dfdcfb24d68a39631b1601ed69f9 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Fri, 31 Oct 2025 12:28:08 +0700 Subject: [PATCH 138/232] Update dependencies.yml (#227) * Update dependencies.yml Refactor the weekly dependencies workflow to inline cargo update steps, auto-generate commit messages and PR bodies with update logs, and use the create-pull-request action to open update PRs on a dedicated branch. Enhancements: Define environment variables for GitHub token, branch name, PR title, and PR body including cargo update logs Inline checkout, Rust toolchain setup, and cargo update command with log cleanup instead of relying on an external workflow Craft commit messages and PR bodies dynamically by capturing and formatting cargo update output Use peter-evans/create-pull-request to push Cargo.lock updates to a 'cargo-update' branch CI: Move permissions and GitHub token configuration into the job context Explicitly set the runner to ubuntu-latest and remove the top-level empty permissions block Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update .github/workflows/dependencies.yml Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --------- Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> --- .github/workflows/dependencies.yml | 52 ++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 7 deletions(-) diff --git a/.github/workflows/dependencies.yml b/.github/workflows/dependencies.yml index d3ec66f9d214d..0e51587b94623 100644 --- a/.github/workflows/dependencies.yml +++ b/.github/workflows/dependencies.yml @@ -2,18 +2,56 @@ name: dependencies -permissions: {} - on: schedule: - - cron: "0 0 * * SUN" # Run weekly on Sundays at midnight UTC - workflow_dispatch: # Needed so we can run it manually + # Run weekly + - cron: "0 0 * * SUN" + workflow_dispatch: + # Needed so we can run it manually +env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + BRANCH: cargo-update + TITLE: "chore(deps): weekly `cargo update`" + BODY: | + Automation to keep dependencies in `Cargo.lock` current. +
cargo update log +

+ ```log + $cargo_update_log + ``` +

+
jobs: update: - uses: ithacaxyz/ci/.github/workflows/cargo-update-pr.yml@9c8d0dc20e7ad02455d3fdab2378a05f29907630 # main + name: Update + runs-on: ubuntu-latest permissions: contents: write pull-requests: write - secrets: - token: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@nightly + + - name: cargo update + # Remove first line that always just says "Updating crates.io index" + run: cargo update --color never 2>&1 | sed '/crates.io index/d' | tee cargo_update.log + + - name: craft commit message and PR body + id: msg + run: | + export cargo_update_log="$(cat cargo_update.log)" + echo "commit_message<> $GITHUB_OUTPUT + printf "$TITLE\n\n$cargo_update_log\n" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + echo "body<> $GITHUB_OUTPUT + echo "$BODY" | envsubst >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + - name: Create Pull Request + uses: peter-evans/create-pull-request@v6 + with: + add-paths: ./Cargo.lock + commit-message: ${{ steps.msg.outputs.commit_message }} + title: ${{ env.TITLE }} + body: ${{ steps.msg.outputs.body }} + branch: ${{ env.BRANCH }} From 1b91245ea6ebda033002225a7abffeb6109280d3 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Fri, 31 Oct 2025 14:29:55 +0700 Subject: [PATCH 139/232] Update npm.yml (#228) CI: Add comment to the Publish Binary step indicating it runs automatically after a successful release workflow or can be triggered manually with a run_id Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- .github/workflows/npm.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/npm.yml b/.github/workflows/npm.yml index b410a80d7d11f..1b2437288eb64 100644 --- a/.github/workflows/npm.yml +++ b/.github/workflows/npm.yml @@ -184,7 +184,8 @@ jobs: exit 1 fi fi - + + # Run automatically after a successful 'release' workflow, or manually if a run_id is provided - name: Publish ${{ matrix.os }}-${{ matrix.arch }} Binary ARTIFACT_DIR: ${{ steps.paths.outputs.artifact_dir }} env: From f652ebab934253f0b1ca21a1131ad7f3e0523067 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Sat, 1 Nov 2025 00:25:46 +0700 Subject: [PATCH 140/232] Update snyk-container.yml (#229) Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- .github/workflows/snyk-container.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/snyk-container.yml b/.github/workflows/snyk-container.yml index 10ac023cf51fc..f07df9c75c8d1 100644 --- a/.github/workflows/snyk-container.yml +++ b/.github/workflows/snyk-container.yml @@ -2,7 +2,7 @@ # They are provided by a third-party and are governed by # separate terms of service, privacy policy, and support # documentation. - +# # A sample workflow which checks out the code, builds a container # image using Docker and scans that image for vulnerabilities using # Snyk. The results are then uploaded to GitHub Security Code Scanning From a63cc1a5e96d2ded9140ed74eaccf6f41da3dc47 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Sat, 1 Nov 2025 01:22:41 +0700 Subject: [PATCH 141/232] Update nextest.yml (#230) Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- .github/workflows/nextest.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nextest.yml b/.github/workflows/nextest.yml index edd230a05a5d9..c1343dcc6d64c 100644 --- a/.github/workflows/nextest.yml +++ b/.github/workflows/nextest.yml @@ -1,5 +1,4 @@ # Reusable workflow for running tests via `cargo nextest` - name: nextest permissions: {} @@ -85,6 +84,7 @@ jobs: with: python-version: "3.14" - name: Install Vyper + # Also update vyper version in .devcontainer/Dockerfile.dev run: pip --version && pip install vyper==0.4.3 From 02e3a1b758bf51e3bff13150632731ad18ce3830 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Sun, 2 Nov 2025 02:34:56 +0700 Subject: [PATCH 142/232] Update const.ts (#231) Code Formatting: Removed an extraneous blank line in npm/src/const.ts to improve code cleanliness and consistency. Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- npm/src/const.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/npm/src/const.ts b/npm/src/const.ts index 42a352712c6ba..890dc5d384767 100644 --- a/npm/src/const.ts +++ b/npm/src/const.ts @@ -1,5 +1,4 @@ import type * as Process from 'node:process' - const ALLOWED_REGISTRY_HOSTS = [ 'registry.npmjs.org', 'registry.yarnpkg.com', From 297291cb60a6fb32893366d6bf500709b9519ca5 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Wed, 5 Nov 2025 14:26:12 +0700 Subject: [PATCH 143/232] Revert "Create web3_defi_gamefi.yml (#61)" (#233) This reverts commit 8575916b7675f246b54daf70cfddccb3f5b97fb0. From 5f89e0e224f7c3cdeeb56dad7af71e156e7e037f Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Thu, 6 Nov 2025 12:30:48 +0700 Subject: [PATCH 144/232] Create deploy.yml (#240) * Create deploy.yml CI: Add GitHub Actions workflow to build the Rust project, run tests, and build a Docker image on pushes to main/master Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 106: Workflow does not contain permissions Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --------- Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> --- .github/workflows/deploy.yml | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 .github/workflows/deploy.yml diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000000000..1ab3e63e39815 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,27 @@ +name: Foundry Build & Deploy +permissions: + contents: read +on: + push: + branches: [main, master] +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout repo + uses: actions/checkout@v3 + + - name: Set up Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + override: true + + - name: Build project + run: cargo build --release + + - name: Run tests + run: cargo test + + - name: Docker build + run: docker build -t foundryg-rs From b2aaca372dc4880c4f4b32f0717d7e597f26c0a6 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Sun, 9 Nov 2025 00:16:20 +0700 Subject: [PATCH 145/232] Update dependencies.yml Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- .github/workflows/dependencies.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/dependencies.yml b/.github/workflows/dependencies.yml index 184e5d13f2c73..be3aab19c4eca 100644 --- a/.github/workflows/dependencies.yml +++ b/.github/workflows/dependencies.yml @@ -1,5 +1,4 @@ # Runs `cargo update` periodically. - name: dependencies on: From daa9b24b45532964b73a4140d494b239138dd626 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Sun, 9 Nov 2025 05:07:08 +0700 Subject: [PATCH 146/232] Update dependencies.yml (#247) Improve readability of the GitHub Actions dependencies workflow by adjusting whitespace and adding blank lines CI: Add blank line before the workflow name declaration Insert blank line after the scheduled cron job entry Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- .github/workflows/dependencies.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/dependencies.yml b/.github/workflows/dependencies.yml index be3aab19c4eca..2d7e331e5fffc 100644 --- a/.github/workflows/dependencies.yml +++ b/.github/workflows/dependencies.yml @@ -1,10 +1,12 @@ # Runs `cargo update` periodically. + name: dependencies on: schedule: # Run weekly - cron: "0 0 * * SUN" + workflow_dispatch: # Needed so we can run it manually From 732ee8b2223e8121bfc468c08fc6ffe294cc42a9 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Sun, 9 Nov 2025 05:30:19 +0700 Subject: [PATCH 147/232] Update dependencies.yml (#248) CI: Remove extraneous blank line in .github/workflows/dependencies.yml Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- .github/workflows/dependencies.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/dependencies.yml b/.github/workflows/dependencies.yml index 2d7e331e5fffc..184e5d13f2c73 100644 --- a/.github/workflows/dependencies.yml +++ b/.github/workflows/dependencies.yml @@ -6,7 +6,6 @@ on: schedule: # Run weekly - cron: "0 0 * * SUN" - workflow_dispatch: # Needed so we can run it manually From fdba942106ad15725e4c9da90d1e5c34d6766b39 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Sun, 9 Nov 2025 05:57:11 +0700 Subject: [PATCH 148/232] Update test.yml (#249) CI: Remove dev branch from test workflow triggers Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- .github/workflows/test.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 716abb3648f13..38ddd73f42e6e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -5,7 +5,6 @@ on: branches: - master - main - - dev pull_request: concurrency: From d8c5c3cba74b2e69628e875c8f255d955a4964ff Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Tue, 11 Nov 2025 01:49:26 +0700 Subject: [PATCH 149/232] Update Cargo.lock (#253) Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> From 9d2402a5506f5ec29cf8bf6b86272df8d3fd35f2 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Tue, 11 Nov 2025 06:19:32 +0700 Subject: [PATCH 150/232] Update Cargo.lock (#254) Chores: Regenerate Cargo.lock to update dependencies Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- Cargo.lock | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 830ba11d18833..72f58c7188cec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,7 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 4 - [[package]] name = "addr2line" version = "0.24.2" @@ -10847,3 +10846,5 @@ dependencies = [ "cc", "pkg-config", ] + + From dd9886e8d0adf479abf73df9cc7ab693a1bf877a Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Tue, 11 Nov 2025 06:47:08 +0700 Subject: [PATCH 151/232] Create config.yml (#255) * Create config.yml Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update .circleci/config.yml Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --------- Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> --- .circleci/config.yml | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 .circleci/config.yml diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000000000..e0476fddba507 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,32 @@ +# Use the latest 2.1 version of CircleCI pipeline process engine. +# See: https://circleci.com/docs/configuration-reference +version: 2.1 +# +# Define a job to be invoked later in a workflow. +# See: https://circleci.com/docs/jobs-steps/#jobs-overview & https://circleci.com/docs/configuration-reference/#jobs +jobs: + say-hello: + # Specify the execution environment. You can specify an image from Docker Hub or use one of our convenience images from CircleCI's Developer Hub. + # See: https://circleci.com/docs/executor-intro/ & https://circleci.com/docs/configuration-reference/#executor-job + docker: + # Specify the version you desire here + # See: https://circleci.com/developer/images/image/cimg/base + - image: cimg/base:2024.06 + # + # Add steps to the job + # See: https://circleci.com/docs/jobs-steps/#steps-overview & https://circleci.com/docs/configuration-reference/#steps + steps: + # Checkout the code as the first step. + - checkout + - run: + name: "Say hello" + command: "echo Hello, World!" +# +# Orchestrate jobs using workflows +# See: https://circleci.com/docs/workflows/ & https://circleci.com/docs/configuration-reference/#workflows +workflows: + say-hello-workflow: # This is the name of the workflow, feel free to change it to better match your workflow. + # Inside the workflow, you define the jobs you want to run. + jobs: + - say-hello + From 724151fc36e84a1bbf337b4421d7ceb3d0a0cbe3 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Wed, 12 Nov 2025 12:13:25 +0700 Subject: [PATCH 152/232] Update config.yml (#256) Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- .circleci/config.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 76b2889f1c4b2..4168efef0971f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,20 +1,20 @@ # Use the latest 2.1 version of CircleCI pipeline process engine. -# See: https://circleci.com/docs/configuration-reference +# See: https://circleci.com/docs/reference/configuration-reference version: 2.1 # Define a job to be invoked later in a workflow. -# See: https://circleci.com/docs/jobs-steps/#jobs-overview & https://circleci.com/docs/configuration-reference/#jobs +# See: https://circleci.com/docs/guides/orchestrate/jobs-steps/#jobs-overview & https://circleci.com/docs/reference/configuration-reference/#jobs jobs: say-hello: # Specify the execution environment. You can specify an image from Docker Hub or use one of our convenience images from CircleCI's Developer Hub. - # See: https://circleci.com/docs/executor-intro/ & https://circleci.com/docs/configuration-reference/#executor-job + # See: https://circleci.com/docs/guides/execution-managed/executor-intro/ & https://circleci.com/docs/reference/configuration-reference/#executor-job docker: # Specify the version you desire here # See: https://circleci.com/developer/images/image/cimg/base - image: cimg/base:current # Add steps to the job - # See: https://circleci.com/docs/jobs-steps/#steps-overview & https://circleci.com/docs/configuration-reference/#steps + # See: https://circleci.com/docs/guides/orchestrate/jobs-steps/#steps-overview & https://circleci.com/docs/reference/configuration-reference/#steps steps: # Checkout the code as the first step. - checkout @@ -23,7 +23,7 @@ jobs: command: "echo Hello, World!" # Orchestrate jobs using workflows -# See: https://circleci.com/docs/workflows/ & https://circleci.com/docs/configuration-reference/#workflows +# See: https://circleci.com/docs/guides/orchestrate/workflows/ & https://circleci.com/docs/reference/configuration-reference/#workflows workflows: say-hello-workflow: # This is the name of the workflow, feel free to change it to better match your workflow. # Inside the workflow, you define the jobs you want to run. From 810d81ce1c61ca91a9d2f55a70053cb3b8e22457 Mon Sep 17 00:00:00 2001 From: "snyk-io[bot]" <141718529+snyk-io[bot]@users.noreply.github.com> Date: Sun, 30 Nov 2025 15:21:45 +0000 Subject: [PATCH 153/232] fix: upgrade tsdown from 0.15.12 to 0.16.1 Snyk has created this PR to upgrade tsdown from 0.15.12 to 0.16.1. See this package in npm: tsdown See this project in Snyk: https://app.snyk.io/org/dargon789/project/8da85645-409e-46fa-bd46-9b58e7905fb8?utm_source=github-cloud-app&utm_medium=referral&page=upgrade-pr --- npm/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/npm/package.json b/npm/package.json index 23d091b1cec0c..8575d52837b43 100644 --- a/npm/package.json +++ b/npm/package.json @@ -10,7 +10,7 @@ "clean": "rm -rf bin dist && rm -rf ./@foundry-rs/forge*/bin ./@foundry-rs/forge*/dist ./@foundry-rs/forge*/*.tgz" }, "dependencies": { - "tsdown": "^0.15.1", + "tsdown": "^0.16.1", "typescript": "^5.9.2", "@types/bun": "^1.2.22", "@types/node": "^24.4.0" From bfd383fb0bbef4b366538ec4bce88a85e73339ef Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Wed, 10 Dec 2025 10:49:46 +0700 Subject: [PATCH 154/232] Create google.yml (#266) CI: Introduce a Google Cloud deployment workflow that builds a Docker image, pushes it to Artifact Registry, and deploys it to a GKE cluster on pushes to the main branches. Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- .github/workflows/google.yml | 117 +++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 .github/workflows/google.yml diff --git a/.github/workflows/google.yml b/.github/workflows/google.yml new file mode 100644 index 0000000000000..1295e430ca96a --- /dev/null +++ b/.github/workflows/google.yml @@ -0,0 +1,117 @@ +# This workflow will build a docker container, publish it to Google Container +# Registry, and deploy it to GKE when there is a push to the "main" +# branch. +# +# To configure this workflow: +# +# 1. Enable the following Google Cloud APIs: +# +# - Artifact Registry (artifactregistry.googleapis.com) +# - Google Kubernetes Engine (container.googleapis.com) +# - IAM Credentials API (iamcredentials.googleapis.com) +# +# You can learn more about enabling APIs at +# https://support.google.com/googleapi/answer/6158841. +# +# 2. Ensure that your repository contains the necessary configuration for your +# Google Kubernetes Engine cluster, including deployment.yml, +# kustomization.yml, service.yml, etc. +# +# 3. Create and configure a Workload Identity Provider for GitHub: +# https://github.com/google-github-actions/auth#preferred-direct-workload-identity-federation. +# +# Depending on how you authenticate, you will need to grant an IAM principal +# permissions on Google Cloud: +# +# - Artifact Registry Administrator (roles/artifactregistry.admin) +# - Kubernetes Engine Developer (roles/container.developer) +# +# You can learn more about setting IAM permissions at +# https://cloud.google.com/iam/docs/manage-access-other-resources +# +# 5. Change the values in the "env" block to match your values. + +name: 'Build and Deploy to GKE' + +on: + push: + branches: + - '"main"' + - '"master"' + +env: + PROJECT_ID: 'my-project' # TODO: update to your Google Cloud project ID + GAR_LOCATION: 'us-central1' # TODO: update to your region + GKE_CLUSTER: 'cluster-1' # TODO: update to your cluster name + GKE_ZONE: 'us-central1-c' # TODO: update to your cluster zone + DEPLOYMENT_NAME: 'gke-test' # TODO: update to your deployment name + REPOSITORY: 'samples' # TODO: update to your Artifact Registry docker repository name + IMAGE: 'static-site' + WORKLOAD_IDENTITY_PROVIDER: 'projects/123456789/locations/global/workloadIdentityPools/my-pool/providers/my-provider' # TODO: update to your workload identity provider + +jobs: + setup-build-publish-deploy: + name: 'Setup, Build, Publish, and Deploy' + runs-on: 'ubuntu-latest' + environment: 'production' + + permissions: + contents: 'read' + id-token: 'write' + + steps: + - name: 'Checkout' + uses: 'actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332' # actions/checkout@v4 + + # Configure Workload Identity Federation and generate an access token. + # + # See https://github.com/google-github-actions/auth for more options, + # including authenticating via a JSON credentials file. + - id: 'auth' + name: 'Authenticate to Google Cloud' + uses: 'google-github-actions/auth@f112390a2df9932162083945e46d439060d66ec2' # google-github-actions/auth@v2 + with: + workload_identity_provider: '${{ env.WORKLOAD_IDENTITY_PROVIDER }}' + + # Authenticate Docker to Google Cloud Artifact Registry + - name: 'Docker Auth' + uses: 'docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567' # docker/login-action@v3 + with: + username: 'oauth2accesstoken' + password: '${{ steps.auth.outputs.auth_token }}' + registry: '${{ env.GAR_LOCATION }}-docker.pkg.dev' + + # Get the GKE credentials so we can deploy to the cluster + - name: 'Set up GKE credentials' + uses: 'google-github-actions/get-gke-credentials@6051de21ad50fbb1767bc93c11357a49082ad116' # google-github-actions/get-gke-credentials@v2 + with: + cluster_name: '${{ env.GKE_CLUSTER }}' + location: '${{ env.GKE_ZONE }}' + + # Build the Docker image + - name: 'Build and push Docker container' + run: |- + DOCKER_TAG="${GAR_LOCATION}-docker.pkg.dev/${PROJECT_ID}/${REPOSITORY}/${IMAGE}:${GITHUB_SHA}" + + docker build \ + --tag "${DOCKER_TAG}" \ + --build-arg GITHUB_SHA="${GITHUB_SHA}" \ + --build-arg GITHUB_REF="${GITHUB_REF}" \ + . + + docker push "${DOCKER_TAG}" + + # Set up kustomize + - name: 'Set up Kustomize' + run: |- + curl -sfLo kustomize https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize%2Fv5.4.3/kustomize_v5.4.3_linux_amd64.tar.gz + chmod u+x ./kustomize + + # Deploy the Docker image to the GKE cluster + - name: 'Deploy to GKE' + run: |- + # replacing the image name in the k8s template + ./kustomize edit set image LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE:TAG=$GAR_LOCATION-docker.pkg.dev/$PROJECT_ID/$REPOSITORY/$IMAGE:$GITHUB_SHA + ./kustomize build . | kubectl apply -f - + kubectl rollout status deployment/$DEPLOYMENT_NAME + kubectl get services -o wide From 2c467d94ca1398ba1a6d2f3542a92d2d16f911af Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Sat, 13 Dec 2025 22:40:34 +0700 Subject: [PATCH 155/232] Update flake.lock (#269) Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- flake.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/flake.lock b/flake.lock index e02008bf849af..af5e606fbc1de 100644 --- a/flake.lock +++ b/flake.lock @@ -8,11 +8,11 @@ "rust-analyzer-src": "rust-analyzer-src" }, "locked": { - "lastModified": 1760856120, - "narHash": "sha256-yH1K/WDJpwIIw7e3wKdRgwHAZ38LXgcGE2Ecvk3I6GU=", + "lastModified": 1757745213, + "narHash": "sha256-P9VX/P2mN96MkFN8hwCYUQ+LV1bfH57UJ/pGwjd0Olc=", "owner": "nix-community", "repo": "fenix", - "rev": "b435bfccee71c6591dbce2fcfabe3e17e98c09fa", + "rev": "1458349a1bd55105f917e962dca4b328ac0a55e8", "type": "github" }, "original": { @@ -23,11 +23,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1760872779, - "narHash": "sha256-c5C907Raf9eY8f1NUXYeju9aUDlm227s/V0OptEbypA=", + "lastModified": 1757746433, + "narHash": "sha256-fEvTiU4s9lWgW7mYEU/1QUPirgkn+odUBTaindgiziY=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "63bdb5d90fa2fa11c42f9716ad1e23565613b07c", + "rev": "6d7ec06d6868ac6d94c371458fc2391ded9ff13d", "type": "github" }, "original": { @@ -46,11 +46,11 @@ "rust-analyzer-src": { "flake": false, "locked": { - "lastModified": 1760714286, - "narHash": "sha256-WOt9KquZ1BXjMcVyHpMeliqNRL6BfRvBHFGfRDriDx4=", + "lastModified": 1757362324, + "narHash": "sha256-/PAhxheUq4WBrW5i/JHzcCqK5fGWwLKdH6/Lu1tyS18=", "owner": "rust-lang", "repo": "rust-analyzer", - "rev": "1e20331e42449dfc0b44bce84147a06772d045d7", + "rev": "9edc9cbe5d8e832b5864e09854fa94861697d2fd", "type": "github" }, "original": { From ea542a2f2b35e931c9b4b20eb8a806125e2b1e1a Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Sun, 14 Dec 2025 19:23:06 +0700 Subject: [PATCH 156/232] Update flake.nix (#270) Adjust Nix flake development shell configuration for better cross-platform support and simplify dependencies. Enhancements: Remove the dprint dependency from the Nix development shell. Add conditional AppKit framework linkage on Darwin systems in the Nix shell configuration. Drop custom hardeningDisable settings from the Nix development shell definition. https://github.com/apps/gemini-code-assist Code Review This pull request updates the Nix flake configuration to improve cross-platform support and simplify dependencies. The changes include removing dprint and hardeningDisable settings, and conditionally adding the AppKit framework for Darwin systems. While most changes are beneficial, removing dprint from the development shell dependencies while its configuration file remains could cause issues for contributors. I've added a comment regarding this potential inconsistency. Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- flake.nix | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/flake.nix b/flake.nix index 5caaab9934aec..8cf41ed16d3a3 100644 --- a/flake.nix +++ b/flake.nix @@ -19,8 +19,7 @@ lib = pkgs.lib; toolchain = fenix.packages.${system}.stable.toolchain; - in - { + in { default = pkgs.mkShell { nativeBuildInputs = with pkgs; [ pkg-config @@ -29,16 +28,13 @@ # test dependencies solc vyper - dprint nodejs ]; + buildInputs = lib.optionals pkgs.stdenv.isDarwin + [ pkgs.darwin.apple_sdk.frameworks.AppKit ]; packages = with pkgs; [ rust-analyzer-unwrapped ]; - # Remove the hardening added by nix to fix jmalloc compilation error. - # More info: https://github.com/tikv/jemallocator/issues/108 - hardeningDisable = [ "fortify" ]; - # Environment variables RUST_SRC_PATH = "${toolchain}/lib/rustlib/src/rust/library"; LD_LIBRARY_PATH = lib.makeLibraryPath [ pkgs.libusb1 ]; From e45aa66f3dd2ad5d28bf4f9910cb6d99b09c1822 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Sun, 14 Dec 2025 20:18:30 +0700 Subject: [PATCH 157/232] Update Cargo.toml (#271) Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 68e6e2881ff7d..9d2f94aad00cb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,7 +31,7 @@ resolver = "2" version = "1.2.1" edition = "2021" # Remember to update clippy.toml as well -rust-version = "1.86" +rust-version = "1.89.0" authors = ["Foundry Contributors"] license = "MIT OR Apache-2.0" homepage = "https://github.com/foundry-rs/foundry" From c0d08b1943203e4b3bc3fe31805f49ddca6173f0 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Mon, 15 Dec 2025 09:11:32 +0700 Subject: [PATCH 158/232] Update nextest.toml (#272) Adjust test runner configuration for nextest to better handle long-running and specific tests. Enhancements: Introduce a dedicated test group that limits chisel-serial tests to a single thread. Increase the default slow-test timeout period to reduce premature terminations for longer-running tests. Expand the slow-timeout override filter to include both ext_integration and can_test_forge_std tests. Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- .config/nextest.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.config/nextest.toml b/.config/nextest.toml index 2a9a4acd42460..70616d4e45e6b 100644 --- a/.config/nextest.toml +++ b/.config/nextest.toml @@ -1,14 +1,14 @@ [test-groups] +chisel-serial = { max-threads = 1 } [profile.default] retries = { backoff = "exponential", count = 2, delay = "5s", jitter = true } -slow-timeout = { period = "30s", terminate-after = 3 } +slow-timeout = { period = "1m", terminate-after = 3 } [[profile.default.overrides]] -filter = "test(/ext_integration/)" +filter = "test(/ext_integration|can_test_forge_std/)" slow-timeout = { period = "5m", terminate-after = 4 } -# Do not re-run so that `cargo cheats` is ran locally. [[profile.default.overrides]] filter = "package(foundry-cheatcodes-spec)" retries = 0 From 562ffb33383724e4723b3ce71eb330fe06b41033 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Wed, 17 Dec 2025 02:32:57 +0700 Subject: [PATCH 159/232] Update dprint.json (#273) (https://github.com/apps/gemini-code-assist) Code Review This pull request updates the dprint.json configuration file. The changes correctly enable formatting for dprint.json itself by modifying the excludes list, update the JSON and Markdown dprint plugins to their latest versions, and add a final newline to the file for POSIX compliance. These are all good maintenance improvements. The changes have been reviewed and appear to be correct and beneficial. No issues were found. Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- dprint.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dprint.json b/dprint.json index f665622619dd4..bf3ea43b41a11 100644 --- a/dprint.json +++ b/dprint.json @@ -3,10 +3,10 @@ "indentWidth": 2, "useTabs": false, "excludes": [ + "!dprint.json", "!npm/**/*.{json,md,toml}", "!npm/**/*.{js,cjs,mjs,d.ts,d.cts,d.mts,ts,tsx,jsx}", "**/_", - "dprint.json", "**/abi", "**/build", "**/target", @@ -25,8 +25,8 @@ ], "plugins": [ "https://plugins.dprint.dev/toml-0.7.0.wasm", - "https://plugins.dprint.dev/json-0.20.0.wasm", - "https://plugins.dprint.dev/markdown-0.19.0.wasm", + "https://plugins.dprint.dev/json-0.21.0.wasm", + "https://plugins.dprint.dev/markdown-0.20.0.wasm", "https://plugins.dprint.dev/dockerfile-0.3.3.wasm", "https://plugins.dprint.dev/typescript-0.95.11.wasm", "https://plugins.dprint.dev/g-plane/pretty_yaml-v0.5.1.wasm" @@ -57,4 +57,4 @@ "exportDeclaration.sortTypeOnlyExports": "none", "importDeclaration.sortTypeOnlyImports": "none" } -} \ No newline at end of file +} From e8b5cb61e3110121163ea24933796caca5a98299 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Wed, 17 Dec 2025 03:17:24 +0700 Subject: [PATCH 160/232] Update .github/workflows/apisec-scan.yml Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- .github/workflows/apisec-scan.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/apisec-scan.yml b/.github/workflows/apisec-scan.yml index 166d2f8ee0235..e716760284792 100644 --- a/.github/workflows/apisec-scan.yml +++ b/.github/workflows/apisec-scan.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Run APIsec scan uses: apisec-inc/apisec-run-scan@025432089674a28ba8fb55f8ab06c10215e772ea From d72eca45cf6f58fd395089c9b3759b4364fc56c6 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Wed, 17 Dec 2025 03:19:05 +0700 Subject: [PATCH 161/232] Update counter/README.md Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- counter/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/counter/README.md b/counter/README.md index 9265b4558406a..679a7f4518035 100644 --- a/counter/README.md +++ b/counter/README.md @@ -7,7 +7,7 @@ Foundry consists of: - **Forge**: Ethereum testing framework (like Truffle, Hardhat and DappTools). - **Cast**: Swiss army knife for interacting with EVM smart contracts, sending transactions and getting chain data. - **Anvil**: Local Ethereum node, akin to Ganache, Hardhat Network. -- **Chisel**: Fast, utilitarian, and verbose solidity REPL. +- **Chisel**: Fast, utilitarian, and verbose Solidity REPL. ## Documentation From f4ebaa7ee344d1bb6aeefade0e9b1512bc4869b9 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Wed, 17 Dec 2025 03:19:58 +0700 Subject: [PATCH 162/232] Update .github/ISSUE_TEMPLATE/bug_report.md Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- .github/ISSUE_TEMPLATE/bug_report.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 43a59e29b9c29..53a505774ac88 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -31,6 +31,7 @@ If applicable, add screenshots to help explain your problem. **Smartphone (please complete the following information):** - Device: [e.g. iPhone6] - OS: [e.g. iOS8.1] + - Browser [e.g. stock browser, Safari] - Browser [e.g. stock browser, safari] - Version [e.g. 22] From d784ebfa40bbae32aaaf7e212c88209b3b83bfc9 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Wed, 24 Dec 2025 20:24:44 +0700 Subject: [PATCH 163/232] Dependabot/cargo/cargo 38744a1864 (#282) * chore(deps): bump alloy-dyn-abi in the cargo group across 1 directory Bumps the cargo group with 1 update in the / directory: [alloy-dyn-abi](https://github.com/alloy-rs/core). Updates `alloy-dyn-abi` from 0.8.25 to 0.8.26 - [Release notes](https://github.com/alloy-rs/core/releases) - [Changelog](https://github.com/alloy-rs/core/blob/v0.8.26/CHANGELOG.md) - [Commits](https://github.com/alloy-rs/core/compare/v0.8.25...v0.8.26) --- updated-dependencies: - dependency-name: alloy-dyn-abi dependency-version: 0.8.26 dependency-type: direct:production dependency-group: cargo ... Signed-off-by: dependabot[bot] * Update and rename ci.yml to cargo.yml (#268) Update CircleCI configuration to use a different Rust toolchain image and rename the workflow file. Build: Rename the CircleCI configuration file from ci.yml to cargo.yml. Change the CircleCI Docker image to use Rust 1.78.0 instead of 1.88.0. Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --------- Signed-off-by: dependabot[bot] Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .circleci/{ci.yml => cargo.yml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .circleci/{ci.yml => cargo.yml} (100%) diff --git a/.circleci/ci.yml b/.circleci/cargo.yml similarity index 100% rename from .circleci/ci.yml rename to .circleci/cargo.yml From a531ef8fa32491e1b4ca0571cd7095db5fb40b30 Mon Sep 17 00:00:00 2001 From: Gengar Date: Wed, 24 Dec 2025 16:21:10 +0200 Subject: [PATCH 164/232] Fix cloning of compiler settings for Vyper input Replace context.clone().compiler_settings.vyper with context.compiler_settings.vyper.clone() to avoid unnecessary cloning of the entire VerificationContext. This reduces memory allocations when creating VyperInput instances. Applied to both etherscan and sourcify verification providers. --- crates/verify/src/etherscan/standard_json.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/verify/src/etherscan/standard_json.rs b/crates/verify/src/etherscan/standard_json.rs index 8a38485e48922..0471e3e42888e 100644 --- a/crates/verify/src/etherscan/standard_json.rs +++ b/crates/verify/src/etherscan/standard_json.rs @@ -56,7 +56,7 @@ impl EtherscanSourceProvider for EtherscanStandardJsonSource { let sources = Source::read_all_from(path, &["vy", "vyi"])?; let input = VyperInput::new( sources, - context.clone().compiler_settings.vyper, + context.compiler_settings.vyper.clone(), &context.compiler_version, ); From d1d564ff1c9fbe1d5cb27c5ee0fcfd33b09650e5 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Thu, 25 Dec 2025 00:52:27 +0700 Subject: [PATCH 165/232] Update config.yml (#283) Summary by Sourcery Update CircleCI pipeline to use a custom Docker executor and job tailored to the project instead of the example hello-world workflow. Enhancements: Introduce a reusable custom executor that pulls from the stable cimg/base Docker image with Docker Hub authentication. CI: Replace the sample say-hello job and workflow with a project-specific job and workflow wired to the new custom executor in .circleci/config.yml. Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- .circleci/config.yml | 42 ++++++++++++++++++------------------------ 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index e0476fddba507..ad53a8e498202 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,32 +1,26 @@ # Use the latest 2.1 version of CircleCI pipeline process engine. # See: https://circleci.com/docs/configuration-reference + version: 2.1 -# -# Define a job to be invoked later in a workflow. -# See: https://circleci.com/docs/jobs-steps/#jobs-overview & https://circleci.com/docs/configuration-reference/#jobs -jobs: - say-hello: - # Specify the execution environment. You can specify an image from Docker Hub or use one of our convenience images from CircleCI's Developer Hub. - # See: https://circleci.com/docs/executor-intro/ & https://circleci.com/docs/configuration-reference/#executor-job +executors: + my-custom-executor: docker: - # Specify the version you desire here - # See: https://circleci.com/developer/images/image/cimg/base - - image: cimg/base:2024.06 - # - # Add steps to the job - # See: https://circleci.com/docs/jobs-steps/#steps-overview & https://circleci.com/docs/configuration-reference/#steps + - image: cimg/base:stable + auth: + # ensure you have first added these secrets + # visit app.circleci.com/settings/project/github/Dargon789/foundry/environment-variables + username: $DOCKER_HUB_USER + password: $DOCKER_HUB_PASSWORD +jobs: + web3-defi-game-project-: + + executor: my-custom-executor steps: - # Checkout the code as the first step. - checkout - - run: - name: "Say hello" - command: "echo Hello, World!" -# -# Orchestrate jobs using workflows -# See: https://circleci.com/docs/workflows/ & https://circleci.com/docs/configuration-reference/#workflows + - run: | + # echo Hello, World! + workflows: - say-hello-workflow: # This is the name of the workflow, feel free to change it to better match your workflow. - # Inside the workflow, you define the jobs you want to run. + my-custom-workflow: jobs: - - say-hello - + - web3-defi-game-project- From 7214be116217e999bddb05a6163a0b255c279a68 Mon Sep 17 00:00:00 2001 From: Haythem Sellami <17862704+haythemsellami@users.noreply.github.com> Date: Sun, 28 Dec 2025 20:33:12 +0700 Subject: [PATCH 166/232] fix: use network-specific BaseFeeParams for Optimism in Anvil --- Cargo.lock | 2 + crates/anvil/src/config.rs | 6 +- crates/anvil/src/eth/backend/mem/mod.rs | 3 +- crates/anvil/src/eth/fees.rs | 25 +++++--- crates/anvil/tests/it/optimism.rs | 80 ++++++++++++++++++++++++- crates/evm/networks/Cargo.toml | 2 + crates/evm/networks/src/lib.rs | 19 ++++++ 7 files changed, 125 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2f043ac4bd3b5..2a36076e9880b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4974,7 +4974,9 @@ name = "foundry-evm-networks" version = "1.5.1" dependencies = [ "alloy-chains", + "alloy-eips", "alloy-evm", + "alloy-op-hardforks", "alloy-primitives", "clap", "revm", diff --git a/crates/anvil/src/config.rs b/crates/anvil/src/config.rs index c0ef7c922ec9d..59e79bfe3a989 100644 --- a/crates/anvil/src/config.rs +++ b/crates/anvil/src/config.rs @@ -16,7 +16,7 @@ use crate::{ }; use alloy_chains::Chain; use alloy_consensus::BlockHeader; -use alloy_eips::eip7840::BlobParams; +use alloy_eips::{eip1559::BaseFeeParams, eip7840::BlobParams}; use alloy_evm::EvmEnv; use alloy_genesis::Genesis; use alloy_network::{AnyNetwork, TransactionResponse}; @@ -1094,6 +1094,9 @@ impl NodeConfig { self.networks, ); + let base_fee_params: BaseFeeParams = + self.networks.base_fee_params(self.get_genesis_timestamp()); + let fees = FeeManager::new( spec_id, self.get_base_fee(), @@ -1101,6 +1104,7 @@ impl NodeConfig { self.get_gas_price(), self.get_blob_excess_gas_and_price(), self.get_blob_params(), + base_fee_params, ); let (db, fork): (Arc>>, Option) = diff --git a/crates/anvil/src/eth/backend/mem/mod.rs b/crates/anvil/src/eth/backend/mem/mod.rs index adc56fe33a711..c46669e439df7 100644 --- a/crates/anvil/src/eth/backend/mem/mod.rs +++ b/crates/anvil/src/eth/backend/mem/mod.rs @@ -41,7 +41,6 @@ use alloy_consensus::{ use alloy_eip5792::{Capabilities, DelegationCapability}; use alloy_eips::{ BlockNumHash, Encodable2718, - eip1559::BaseFeeParams, eip4844::{BlobTransactionSidecar, kzg_to_versioned_hash}, eip7840::BlobParams, eip7910::SystemContract, @@ -1857,7 +1856,7 @@ impl Backend { block_env.basefee = simulated_block .inner .header - .next_block_base_fee(BaseFeeParams::ethereum()) + .next_block_base_fee(self.fees.base_fee_params()) .unwrap_or_default(); block_res.push(simulated_block); diff --git a/crates/anvil/src/eth/fees.rs b/crates/anvil/src/eth/fees.rs index e34b7c6eb6a24..0e4c6dffef57f 100644 --- a/crates/anvil/src/eth/fees.rs +++ b/crates/anvil/src/eth/fees.rs @@ -36,10 +36,6 @@ pub const BASE_FEE_CHANGE_DENOMINATOR: u128 = 8; /// Minimum suggested priority fee pub const MIN_SUGGESTED_PRIORITY_FEE: u128 = 1e9 as u128; -pub fn default_elasticity() -> f64 { - 1f64 / BaseFeeParams::ethereum().elasticity_multiplier as f64 -} - /// Stores the fee related information #[derive(Clone, Debug)] pub struct FeeManager { @@ -62,6 +58,8 @@ pub struct FeeManager { /// This will be constant value unless changed manually gas_price: Arc>, elasticity: Arc>, + /// Network-specific base fee params for EIP-1559 calculations + base_fee_params: BaseFeeParams, } impl FeeManager { @@ -72,7 +70,9 @@ impl FeeManager { gas_price: u128, blob_excess_gas_and_price: BlobExcessGasAndPrice, blob_params: BlobParams, + base_fee_params: BaseFeeParams, ) -> Self { + let elasticity = 1f64 / base_fee_params.elasticity_multiplier as f64; Self { spec_id, blob_params: Arc::new(RwLock::new(blob_params)), @@ -80,10 +80,16 @@ impl FeeManager { is_min_priority_fee_enforced, gas_price: Arc::new(RwLock::new(gas_price)), blob_excess_gas_and_price: Arc::new(RwLock::new(blob_excess_gas_and_price)), - elasticity: Arc::new(RwLock::new(default_elasticity())), + elasticity: Arc::new(RwLock::new(elasticity)), + base_fee_params, } } + /// Returns the base fee params used for EIP-1559 calculations + pub fn base_fee_params(&self) -> BaseFeeParams { + self.base_fee_params + } + pub fn elasticity(&self) -> f64 { *self.elasticity.read() } @@ -156,7 +162,7 @@ impl FeeManager { if self.base_fee() == 0 { return 0; } - calculate_next_block_base_fee(gas_used, gas_limit, last_fee_per_gas) + calc_next_block_base_fee(gas_used, gas_limit, last_fee_per_gas, self.base_fee_params) } /// Calculates the next block blob base fee. @@ -185,7 +191,12 @@ impl FeeManager { } } -/// Calculate base fee for next block. [EIP-1559](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1559.md) spec +/// Calculate base fee for next block using Ethereum mainnet parameters. +/// +/// See [EIP-1559](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1559.md) spec. +/// +/// Note: This uses Ethereum's base fee params. For network-specific calculations +/// (e.g., Optimism), use [`FeeManager::get_next_block_base_fee_per_gas`] instead. pub fn calculate_next_block_base_fee(gas_used: u64, gas_limit: u64, base_fee: u64) -> u64 { calc_next_block_base_fee(gas_used, gas_limit, base_fee, BaseFeeParams::ethereum()) } diff --git a/crates/anvil/tests/it/optimism.rs b/crates/anvil/tests/it/optimism.rs index 1dbef5eb1e5fc..3eb3fa341a30f 100644 --- a/crates/anvil/tests/it/optimism.rs +++ b/crates/anvil/tests/it/optimism.rs @@ -5,9 +5,9 @@ use alloy_eips::eip2718::Encodable2718; use alloy_network::{EthereumWallet, TransactionBuilder}; use alloy_primitives::{Address, Bloom, TxHash, TxKind, U256, b256}; use alloy_provider::Provider; -use alloy_rpc_types::TransactionRequest; +use alloy_rpc_types::{BlockId, TransactionRequest}; use alloy_serde::WithOtherFields; -use anvil::{NodeConfig, spawn}; +use anvil::{NodeConfig, eth::fees::INITIAL_BASE_FEE, spawn}; use foundry_evm_networks::NetworkConfigs; use op_alloy_consensus::TxDeposit; use op_alloy_rpc_types::OpTransactionFields; @@ -270,3 +270,79 @@ fn preserves_op_fields_in_convert_to_anvil_receipt() { assert_eq!(got, Some(expected), "field `{key}` mismatch"); } } + +const GAS_TRANSFER: u64 = 21_000; + +/// Test that Optimism uses Canyon base fee params instead of Ethereum params. +/// +/// Optimism Canyon uses different EIP-1559 parameters: +/// - elasticity_multiplier: 6 (vs Ethereum's 2) +/// - base_fee_max_change_denominator: 250 (vs Ethereum's 8) +/// +/// This means with a full block: +/// - Ethereum: base_fee increases by base_fee * 1 / 8 = 12.5% +/// - Optimism: base_fee increases by base_fee * 5 / 250 = 2% +#[tokio::test(flavor = "multi_thread")] +async fn test_optimism_base_fee_params() { + // Spawn an Optimism node with a gas limit equal to one transfer (full block scenario) + let (_api, handle) = spawn( + NodeConfig::test() + .with_networks(NetworkConfigs::with_optimism()) + .with_base_fee(Some(INITIAL_BASE_FEE)) + .with_gas_limit(Some(GAS_TRANSFER)), + ) + .await; + + let wallet = handle.dev_wallets().next().unwrap(); + let signer: EthereumWallet = wallet.clone().into(); + + let provider = http_provider_with_signer(&handle.http_endpoint(), signer); + + let tx = TransactionRequest::default().to(Address::random()).with_value(U256::from(1337)); + let tx = WithOtherFields::new(tx); + + // Send first transaction to fill the block + provider.send_transaction(tx.clone()).await.unwrap().get_receipt().await.unwrap(); + + let base_fee = provider + .get_block(BlockId::latest()) + .await + .unwrap() + .unwrap() + .header + .base_fee_per_gas + .unwrap(); + + // Send second transaction to fill the next block + provider.send_transaction(tx.clone()).await.unwrap().get_receipt().await.unwrap(); + + let next_base_fee = provider + .get_block(BlockId::latest()) + .await + .unwrap() + .unwrap() + .header + .base_fee_per_gas + .unwrap(); + + assert!(next_base_fee > base_fee, "base fee should increase with full block"); + + // Optimism Canyon formula: base_fee * (elasticity - 1) / denominator = base_fee * 5 / 250 + // = INITIAL_BASE_FEE * 5 / 250 = 1_000_000_000 * 5 / 250 = 20_000_000 + // + // Note: Ethereum would be INITIAL_BASE_FEE + 125_000_000 (12.5% increase) + let expected_op_increase = INITIAL_BASE_FEE * 5 / 250; // 2% increase = 20_000_000 + assert_eq!( + next_base_fee, + INITIAL_BASE_FEE + expected_op_increase, + "Optimism should use Canyon base fee params (2% max increase), not Ethereum's (12.5%)" + ); + + // Explicitly verify it's NOT using Ethereum params (which would give 12.5% increase) + let ethereum_increase = INITIAL_BASE_FEE / 8; // 125_000_000 + assert_ne!( + next_base_fee, + INITIAL_BASE_FEE + ethereum_increase, + "Should not be using Ethereum base fee params" + ); +} diff --git a/crates/evm/networks/Cargo.toml b/crates/evm/networks/Cargo.toml index b3bc2701ed3bb..934458a42165b 100644 --- a/crates/evm/networks/Cargo.toml +++ b/crates/evm/networks/Cargo.toml @@ -15,7 +15,9 @@ workspace = true [dependencies] alloy-chains.workspace = true +alloy-eips.workspace = true alloy-evm.workspace = true +alloy-op-hardforks.workspace = true alloy-primitives = { workspace = true, features = [ "serde", "getrandom", diff --git a/crates/evm/networks/src/lib.rs b/crates/evm/networks/src/lib.rs index 3f327e15617a5..8e64589bb71ad 100644 --- a/crates/evm/networks/src/lib.rs +++ b/crates/evm/networks/src/lib.rs @@ -9,7 +9,9 @@ use alloy_chains::{ NamedChain, NamedChain::{Chiado, Gnosis, Moonbase, Moonbeam, MoonbeamDev, Moonriver, Rsk, RskTestnet}, }; +use alloy_eips::eip1559::BaseFeeParams; use alloy_evm::precompiles::PrecompilesMap; +use alloy_op_hardforks::{OpChainHardforks, OpHardforks}; use alloy_primitives::{Address, map::AddressHashMap}; use clap::Parser; use serde::{Deserialize, Serialize}; @@ -47,6 +49,23 @@ impl NetworkConfigs { self.optimism } + /// Returns the base fee parameters for the configured network. + /// + /// For Optimism networks, returns Canyon parameters if the Canyon hardfork is active + /// at the given timestamp, otherwise returns pre-Canyon parameters. + pub fn base_fee_params(&self, timestamp: u64) -> BaseFeeParams { + if self.is_optimism() { + let op_hardforks = OpChainHardforks::op_mainnet(); + if op_hardforks.is_canyon_active_at_timestamp(timestamp) { + BaseFeeParams::optimism_canyon() + } else { + BaseFeeParams::optimism() + } + } else { + BaseFeeParams::ethereum() + } + } + pub fn bypass_prevrandao(&self, chain_id: u64) -> bool { if let Ok( Moonbeam | Moonbase | Moonriver | MoonbeamDev | Rsk | RskTestnet | Gnosis | Chiado, From 17250c474507d3a960742dcec147d8ff212a379b Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Wed, 31 Dec 2025 20:48:07 +0700 Subject: [PATCH 167/232] Dargon789 patch 1 (#285) * Update test.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Update test.yml (#167) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Delete .circleci/ci_v1.yml (#173) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Update cargo.yml (#174) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Delete .circleci/config.yml Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 74: Artifact poisoning Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 83: Uncontrolled data used in path expression Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 93: Uncontrolled data used in path expression Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 76: Artifact poisoning Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 94: Uncontrolled data used in path expression Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 80: Server-side request forgery Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update cargo.yml (#210) https://github.com/apps/gemini-code-assist ------------------- Code Review This pull request downgrades the Rust version in the CI pipeline from 1.88.0 to 1.87.0. This is inconsistent with the project's declared Minimum Supported Rust Version (MSRV) of 1.89 in Cargo.toml. My review highlights this discrepancy and suggests aligning the CI's Rust version with the MSRV to ensure the project's compatibility guarantees are properly tested. --------------- Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Fix cloning of compiler settings for Vyper input Replace context.clone().compiler_settings.vyper with context.compiler_settings.vyper.clone() to avoid unnecessary cloning of the entire VerificationContext. This reduces memory allocations when creating VyperInput instances. Applied to both etherscan and sourcify verification providers. --------- Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Co-authored-by: Gengar --- .circleci/config.yml | 32 ------------------- benches/src/lib.rs | 16 ++++++++-- crates/evm/evm/src/executors/corpus.rs | 33 +++++++++++++++----- crates/test-utils/src/script.rs | 12 +++++++ crates/verify/src/etherscan/standard_json.rs | 2 +- 5 files changed, 52 insertions(+), 43 deletions(-) delete mode 100644 .circleci/config.yml diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index d02c693397345..0000000000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,32 +0,0 @@ -# Use the latest 2.1 version of CircleCI pipeline process engine. -# See: https://circleci.com/docs/reference/configuration-reference -version: 2.1 -# -# Define a job to be invoked later in a workflow. -# See: https://circleci.com/docs/guides/orchestrate/jobs-steps/#jobs-overview & https://circleci.com/docs/reference/configuration-reference/#jobs -jobs: - say-hello: - # Specify the execution environment. You can specify an image from Docker Hub or use one of our convenience images from CircleCI's Developer Hub. - # See: https://circleci.com/docs/guides/execution-managed/executor-intro/ & https://circleci.com/docs/reference/configuration-reference/#executor-job - docker: - # Specify the version you desire here - # See: https://circleci.com/developer/images/image/cimg/base - - image: cimg/base:current - # - # Add steps to the job - # See: https://circleci.com/docs/guides/orchestrate/jobs-steps/#steps-overview & https://circleci.com/docs/reference/configuration-reference/#steps - steps: - # Checkout the code as the first step. - - checkout - - run: - name: "Say hello" - command: "echo Hello, World!" -# -# Orchestrate jobs using workflows -# See: https://circleci.com/docs/guides/orchestrate/workflows/ & https://circleci.com/docs/reference/configuration-reference/#workflows -workflows: - say-hello-workflow: # This is the name of the workflow, feel free to change it to better match your workflow. - # Inside the workflow, you define the jobs you want to run. - jobs: - - say-hello - diff --git a/benches/src/lib.rs b/benches/src/lib.rs index 89629f6898628..eeb3cbeeafe11 100644 --- a/benches/src/lib.rs +++ b/benches/src/lib.rs @@ -132,10 +132,20 @@ impl BenchmarkProject { for entry in std::fs::read_dir(&root_path)? { let entry = entry?; let path = entry.path(); - if path.is_dir() { - std::fs::remove_dir_all(&path).ok(); + // Canonicalize the entry to prevent directory traversal + let canon = match path.canonicalize() { + Ok(p) => p, + Err(_) => continue, // Skip if unable to canonicalize + }; + // Ensure canonicalized path stays strictly within root_path (TempProject root) + if !canon.starts_with(&root_path) { + sh_eprintln!("⚠️ Skipping suspicious path during cleanup: {:?}", canon); + continue; + } + if canon.is_dir() { + std::fs::remove_dir_all(&canon).ok(); } else { - std::fs::remove_file(&path).ok(); + std::fs::remove_file(&canon).ok(); } } diff --git a/crates/evm/evm/src/executors/corpus.rs b/crates/evm/evm/src/executors/corpus.rs index eb5431e3ba57a..92eb4452ce802 100644 --- a/crates/evm/evm/src/executors/corpus.rs +++ b/crates/evm/evm/src/executors/corpus.rs @@ -190,6 +190,15 @@ impl CorpusManager { foundry_common::fs::create_dir_all(corpus_dir)?; } + // Canonicalize the corpus_dir to a trusted absolute path + let canonical_corpus_dir = match corpus_dir.canonicalize() { + Ok(dir) => dir, + Err(e) => { + trace!(target: "corpus", "failed to canonicalize corpus_dir {}: {e}", corpus_dir.display()); + return Err(e.into()); + } + }; + let can_replay_tx = |tx: &BasicTxDetails| -> bool { fuzzed_contracts.is_some_and(|contracts| contracts.targets.lock().can_replay(tx)) || fuzzed_function.is_some_and(|function| { @@ -202,21 +211,31 @@ impl CorpusManager { 'corpus_replay: for entry in std::fs::read_dir(corpus_dir)? { let path = entry?.path(); - if path.is_file() - && let Some(name) = path.file_name().and_then(|s| s.to_str()) + // Canonicalize the candidate path, skip if it cannot be canonicalized (e.g. broken symlink) + let canonical_path = match path.canonicalize() { + Ok(p) => p, + Err(_) => continue, + }; + // Ensure file is inside the corpus directory (prevents path traversal/symlink escape) + if !canonical_path.starts_with(&canonical_corpus_dir) { + trace!(target: "corpus", "Skipping file outside corpus_dir: {}", path.display()); + continue; + } + if canonical_path.is_file() + && let Some(name) = canonical_path.file_name().and_then(|s| s.to_str()) && name.contains(METADATA_SUFFIX) { // Ignore metadata files continue; } - let read_corpus_result = match path.extension().and_then(|ext| ext.to_str()) { - Some("gz") => foundry_common::fs::read_json_gzip_file::>(&path), - _ => foundry_common::fs::read_json_file::>(&path), + let read_corpus_result = match canonical_path.extension().and_then(|ext| ext.to_str()) { + Some("gz") => foundry_common::fs::read_json_gzip_file::>(&canonical_path), + _ => foundry_common::fs::read_json_file::>(&canonical_path), }; let Ok(tx_seq) = read_corpus_result else { - trace!(target: "corpus", "failed to load corpus from {}", path.display()); + trace!(target: "corpus", "failed to load corpus from {}", canonical_path.display()); continue; }; @@ -257,7 +276,7 @@ impl CorpusManager { ); // Populate in memory corpus with the sequence from corpus file. - in_memory_corpus.push(CorpusEntry::new(tx_seq, path)?); + in_memory_corpus.push(CorpusEntry::new(tx_seq, canonical_path.clone())?); } } diff --git a/crates/test-utils/src/script.rs b/crates/test-utils/src/script.rs index 45dbbbebdd73a..626ce94448a4a 100644 --- a/crates/test-utils/src/script.rs +++ b/crates/test-utils/src/script.rs @@ -123,6 +123,18 @@ impl ScriptTester { for entry in fs::read_dir(&from_dir)? { let file = &entry?.path(); let name = file.file_name().unwrap(); + // Validate file name to avoid path traversal and absolute paths + let name_str = name.to_string_lossy(); + if name_str.contains("..") || name_str.contains("/") || name_str.contains("\\") { + // Skip invalid (potentially dangerous) file names + continue; + } + // Optionally verify canonicalized file is in from_dir to avoid symlink traversal + if let Ok(canonical_file) = file.canonicalize() { + if !canonical_file.starts_with(&from_dir) { + continue; + } + } fs::copy(file, to_dir.join(name))?; } Ok(()) diff --git a/crates/verify/src/etherscan/standard_json.rs b/crates/verify/src/etherscan/standard_json.rs index 8a38485e48922..0471e3e42888e 100644 --- a/crates/verify/src/etherscan/standard_json.rs +++ b/crates/verify/src/etherscan/standard_json.rs @@ -56,7 +56,7 @@ impl EtherscanSourceProvider for EtherscanStandardJsonSource { let sources = Source::read_all_from(path, &["vy", "vyi"])?; let input = VyperInput::new( sources, - context.clone().compiler_settings.vyper, + context.compiler_settings.vyper.clone(), &context.compiler_version, ); From 8b29d48133545a0f5c32da2fdc48bb54ac2eb309 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Wed, 31 Dec 2025 21:08:43 +0700 Subject: [PATCH 168/232] merge gh-master (#287) * Create config.yml (#236) Create .circleci/config.yml defining a version 2.1 pipeline with a docker-based "say-hello" job, checkout and echo steps, and a workflow to orchestrate it Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * fix(evm): use timestamp-based blob base fee calculation (#12959) * fix(evm): use timestamp-based blob base fee calculation * chore: use patch * Now BPO1 is default * bump to hardforks to 0.4.7 --------- Co-authored-by: Matthias Seitz * fix(config): reject bare versions in compilation restrictions (#12955) fmt Co-authored-by: tefyosL-sol * Revert "fix(config): err on unknown profile (#12946)" (#12964) This reverts commit 6ff4b52e2e572e93d0cd81591b1bd0e6ad9ed507. * Update crates/config/src/compilation.rs Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --------- Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: cakevm Co-authored-by: Matthias Seitz Co-authored-by: Theodore Solis Co-authored-by: tefyosL-sol Co-authored-by: grandizzy <38490174+grandizzy@users.noreply.github.com> Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- .circleci/config.yml | 31 +++++++++++ Cargo.lock | 8 +-- Cargo.toml | 4 +- crates/anvil/tests/it/anvil_api.rs | 2 +- crates/config/src/compilation.rs | 33 +++++++++++- crates/config/src/lib.rs | 75 +++++++++++++++++--------- crates/evm/core/src/backend/mod.rs | 4 +- crates/forge/tests/cli/test_cmd/mod.rs | 27 ++++++++++ 8 files changed, 148 insertions(+), 36 deletions(-) create mode 100644 .circleci/config.yml diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000000000..d5d401c51893c --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,31 @@ +# Use the latest 2.1 version of CircleCI pipeline process engine. +# See: https://circleci.com/docs/configuration-reference +version: 2.1 + +# Define a job to be invoked later in a workflow. +# See: https://circleci.com/docs/jobs-steps/#jobs-overview & https://circleci.com/docs/configuration-reference/#jobs +jobs: + say-hello: + # Specify the execution environment. You can specify an image from Docker Hub or use one of our convenience images from CircleCI's Developer Hub. + # See: https://circleci.com/docs/executor-intro/ & https://circleci.com/docs/configuration-reference/#executor-job + docker: + # Specify the version you desire here + # See: https://circleci.com/developer/images/image/cimg/base + - image: cimg/base:current + + # Add steps to the job + # See: https://circleci.com/docs/jobs-steps/#steps-overview & https://circleci.com/docs/configuration-reference/#steps + steps: + # Checkout the code as the first step. + - checkout + - run: + name: "Say hello" + command: "echo Hello, World!" + +# Orchestrate jobs using workflows +# See: https://circleci.com/docs/workflows/ & https://circleci.com/docs/configuration-reference/#workflows +workflows: + say-hello-workflow: # This is the name of the workflow, feel free to change it to better match your workflow. + # Inside the workflow, you define the jobs you want to run. + jobs: + - say-hello diff --git a/Cargo.lock b/Cargo.lock index 2f043ac4bd3b5..f19b33e2859ae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -291,9 +291,9 @@ dependencies = [ [[package]] name = "alloy-hardforks" -version = "0.4.5" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d9a33550fc21fd77a3f8b63e99969d17660eec8dcc50a95a80f7c9964f7680b" +checksum = "83ba208044232d14d4adbfa77e57d6329f51bc1acc21f5667bb7db72d88a0831" dependencies = [ "alloy-chains", "alloy-eip2124", @@ -388,9 +388,9 @@ dependencies = [ [[package]] name = "alloy-op-hardforks" -version = "0.4.5" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f96fb2fce4024ada5b2c11d4076acf778a0d3e4f011c6dfd2ffce6d0fcf84ee9" +checksum = "6472c610150c4c4c15be9e1b964c9b78068f933bda25fb9cdf09b9ac2bb66f36" dependencies = [ "alloy-chains", "alloy-hardforks", diff --git a/Cargo.toml b/Cargo.toml index dbeac987c0358..9f9fdc0498bdb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -268,8 +268,8 @@ alloy-transport = { version = "1.1.3", default-features = false } alloy-transport-http = { version = "1.1.3", default-features = false } alloy-transport-ipc = { version = "1.1.3", default-features = false } alloy-transport-ws = { version = "1.1.3", default-features = false } -alloy-hardforks = { version = "0.4.5", default-features = false } -alloy-op-hardforks = { version = "0.4.5", default-features = false } +alloy-hardforks = { version = "0.4.7", default-features = false } +alloy-op-hardforks = { version = "0.4.7", default-features = false } ## alloy-core alloy-dyn-abi = "1.5.1" diff --git a/crates/anvil/tests/it/anvil_api.rs b/crates/anvil/tests/it/anvil_api.rs index fc89206db81fd..e675001d7a480 100644 --- a/crates/anvil/tests/it/anvil_api.rs +++ b/crates/anvil/tests/it/anvil_api.rs @@ -440,7 +440,7 @@ async fn can_get_node_info() { let block_number = provider.get_block_number().await.unwrap(); let block = provider.get_block(BlockId::from(block_number)).await.unwrap().unwrap(); - let hard_fork: &str = SpecId::PRAGUE.into(); + let hard_fork: &str = SpecId::OSAKA.into(); let expected_node_info = NodeInfo { current_block_number: 0_u64, diff --git a/crates/config/src/compilation.rs b/crates/config/src/compilation.rs index 94335dd26a8ef..46f0f2158a0f1 100644 --- a/crates/config/src/compilation.rs +++ b/crates/config/src/compilation.rs @@ -7,7 +7,7 @@ use foundry_compilers::{ solc::{Restriction, SolcRestrictions}, }; use semver::VersionReq; -use serde::{Deserialize, Serialize}; +use serde::{Deserialize, Deserializer, Serialize}; /// Keeps possible overrides for default settings which users may configure to construct additional /// settings profile. @@ -69,6 +69,7 @@ pub enum RestrictionsError { #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct CompilationRestrictions { pub paths: GlobMatcher, + #[serde(default, deserialize_with = "deserialize_version_req")] pub version: Option, pub via_ir: Option, pub bytecode_hash: Option, @@ -85,6 +86,36 @@ pub struct CompilationRestrictions { pub max_evm_version: Option, } +/// Custom deserializer for version field that rejects ambiguous bare version numbers. +fn deserialize_version_req<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + let opt_string: Option = Option::deserialize(deserializer)?; + let Some(opt_string) = opt_string else { + return Ok(None); + }; + + let version = opt_string.trim(); + // Reject bare versions like "0.8.11" that lack an operator prefix + if version.chars().next().is_some_and(|c| c.is_ascii_digit()) { + return Err(serde::de::Error::custom(format!( + "Invalid version format '{version}' in compilation_restrictions. \ + Bare version numbers are ambiguous and default to caret requirements (e.g. '^{version}'). \ + Use an explicit constraint such as '={version}' for an exact version or '>={version}' for a minimum version." + ))); + } + + let req = VersionReq::parse(version).map_err(|e| { + serde::de::Error::custom(format!( + "Invalid version requirement '{version}': {e}. \ + Examples: '=0.8.11' (exact), '>=0.8.11' (minimum), '>=0.8.11 <0.9.0' (range)." + )) + })?; + + Ok(Some(req)) +} + impl TryFrom for RestrictionsWithVersion { type Error = RestrictionsError; diff --git a/crates/config/src/lib.rs b/crates/config/src/lib.rs index 50faf02cbfcb0..d54cb0aac63f5 100644 --- a/crates/config/src/lib.rs +++ b/crates/config/src/lib.rs @@ -774,40 +774,28 @@ impl Config { } fn from_figment(figment: Figment) -> Result { - // Helper to add a profile only if it's not already present - fn add_profile(profiles: &mut Vec, profile: &Profile) { - if !profiles.contains(profile) { - profiles.push(profile.clone()); - } - } - let mut config = figment.extract::().map_err(ExtractConfigError::new)?; - let active_profile = figment.profile().clone(); + config.profile = figment.profile().clone(); - // Collect profiles from the profile section. // The `"profile"` profile contains all the profiles as keys. + let mut add_profile = |profile: &Profile| { + if !config.profiles.contains(profile) { + config.profiles.push(profile.clone()); + } + }; let figment = figment.select(Self::PROFILE_SECTION); if let Ok(data) = figment.data() && let Some(profiles) = data.get(&Profile::new(Self::PROFILE_SECTION)) { for profile in profiles.keys() { - add_profile(&mut config.profiles, &Profile::new(profile)); + add_profile(&Profile::new(profile)); } } - - // Always include the default profile - add_profile(&mut config.profiles, &Self::DEFAULT_PROFILE); - - // Ensure the active profile exists. - if config.profiles.contains(&active_profile) { - config.profile = active_profile; - } else { - return Err(ExtractConfigError::new(Error::from(format!( - "Profile {active_profile} does not exist" - )))); - } + add_profile(&Self::DEFAULT_PROFILE); + add_profile(&config.profile); config.normalize_optimizer_settings(); + Ok(config) } @@ -6427,18 +6415,53 @@ mod tests { } #[test] - fn fails_on_unknown_profile() { + fn fails_on_ambiguous_version_in_compilation_restrictions() { figment::Jail::expect_with(|jail| { jail.create_file( "foundry.toml", r#" [profile.default] + src = "src" + + [[profile.default.compilation_restrictions]] + paths = "src/*.sol" + version = "0.8.11" "#, )?; - jail.set_env("FOUNDRY_PROFILE", "foo"); - let err = Config::load().expect_err("expected unknown profile to fail"); - assert!(err.to_string().contains("Profile foo does not exist")); + let err = Config::load().expect_err("expected bare version to fail"); + let err_msg = err.to_string(); + assert!( + err_msg.contains("Invalid version format '0.8.11'") + && err_msg.contains("Bare version numbers are ambiguous"), + "Expected error about ambiguous version, got: {err_msg}" + ); + + Ok(()) + }); + } + + #[test] + fn accepts_explicit_version_requirements() { + figment::Jail::expect_with(|jail| { + jail.create_file( + "foundry.toml", + r#" + [profile.default] + src = "src" + + [[profile.default.compilation_restrictions]] + paths = "src/*.sol" + version = "=0.8.11" + + [[profile.default.compilation_restrictions]] + paths = "test/*.sol" + version = ">=0.8.11" + "#, + )?; + + let config = Config::load().expect("should accept explicit version requirements"); + assert_eq!(config.compilation_restrictions.len(), 2); Ok(()) }); diff --git a/crates/evm/core/src/backend/mod.rs b/crates/evm/core/src/backend/mod.rs index 26e56e7bf883f..6429ceb3db23f 100644 --- a/crates/evm/core/src/backend/mod.rs +++ b/crates/evm/core/src/backend/mod.rs @@ -6,7 +6,7 @@ use crate::{ evm::new_evm_with_inspector, fork::{CreateFork, ForkId, MultiFork}, state_snapshot::StateSnapshots, - utils::{configure_tx_env, configure_tx_req_env, get_blob_base_fee_update_fraction_by_spec_id}, + utils::{configure_tx_env, configure_tx_req_env, get_blob_base_fee_update_fraction}, }; use alloy_consensus::Typed2718; use alloy_evm::Evm; @@ -1954,7 +1954,7 @@ fn update_env_block(env: &mut EnvMut<'_>, block: &AnyRpcBlock) { if let Some(excess_blob_gas) = block.header.excess_blob_gas { env.block.blob_excess_gas_and_price = Some(BlobExcessGasAndPrice::new( excess_blob_gas, - get_blob_base_fee_update_fraction_by_spec_id(env.cfg.spec), + get_blob_base_fee_update_fraction(env.cfg.chain_id, block.header.timestamp), )); } } diff --git a/crates/forge/tests/cli/test_cmd/mod.rs b/crates/forge/tests/cli/test_cmd/mod.rs index 9666cf4d7e69d..0abffff57c4a8 100644 --- a/crates/forge/tests/cli/test_cmd/mod.rs +++ b/crates/forge/tests/cli/test_cmd/mod.rs @@ -678,6 +678,33 @@ Ran 1 test suite [ELAPSED]: 1 tests passed, 0 failed, 0 skipped (1 total tests) "#]]); }); +// Validates BPO1 blob gas price calculation during fork transaction replay. +// Block 24127158 has a blob tx at index 0, target tx at index 1. +// Forking at the target tx replays the blob tx with correct BPO1 blob base fee calculation. +forgetest_init!(fork_tx_replay_bpo1_blob_base_fee, |prj, cmd| { + let endpoint = rpc::next_http_archive_rpc_url(); + + prj.add_test( + "BlobFork.t.sol", + &r#" +import {Test} from "forge-std/Test.sol"; + +contract BlobForkTest is Test { + function test_fork_with_blob_replay() public { + // Fork at tx index 1 in block 24127158, which replays blob tx at index 0 + bytes32 txHash = 0xa0f349b16e0f338ee760a9954ff5dbf2a402cff3320f3fe2c3755aee8babc335; + vm.createSelectFork("", txHash); + // If we get here, blob tx replay succeeded + assertTrue(true); + } +} + "# + .replace("", &endpoint), + ); + + cmd.args(["test", "-vvvv"]).assert_success(); +}); + // https://github.com/foundry-rs/foundry/issues/6579 forgetest_init!(include_custom_types_in_traces, |prj, cmd| { prj.add_test( From 49754a8131b5ac24511cd478acb414ef279f085e Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Wed, 31 Dec 2025 21:22:25 +0700 Subject: [PATCH 169/232] Foundry/ethereum ux (#284) * Potential fix for code scanning alert no. 19: Workflow does not contain permissions Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 61: Workflow does not contain permissions Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 74: Artifact poisoning Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Create config.yml (#105) * Create cargo.yml (#106) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Delete .github/workflows/docker-image.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Revert "Create cargo.yml (#106)" This reverts commit 251a2b4fce0c50e3426ffb2022d9abef5b948fa9. * Create cargo.yml (#213) https://github.com/apps/gemini-code-assist Code Review This pull request introduces a CircleCI workflow to automate formatting checks and tests. My review has identified two main issues in the configuration: redundant steps that would unnecessarily increase job execution time, and a mismatch between the Rust version in the CI environment and the one specified in the project's Cargo.toml. I've provided suggestions to fix these issues for a more efficient and consistent CI process. Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --------- Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> --- .github/workflows/docker-image.yml | 21 --------------------- 1 file changed, 21 deletions(-) delete mode 100644 .github/workflows/docker-image.yml diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml deleted file mode 100644 index e0c9c518e8748..0000000000000 --- a/.github/workflows/docker-image.yml +++ /dev/null @@ -1,21 +0,0 @@ -name: Docker Image CI - -on: - push: - branches: [ "master" ] - pull_request: - branches: [ "master" ] - -permissions: - contents: read - -jobs: - - build: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - name: Build the Docker image - run: docker build . --file Dockerfile --tag my-image-name:${{ github.sha }} From a859609cb8e0b2112adedec72aa758b1c3183fcf Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Wed, 31 Dec 2025 21:42:42 +0700 Subject: [PATCH 170/232] Gamefi defi (#288) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: ignore RUSTSEC-2025-0137 (#12941) Co-authored-by: Claude * chore(deps): weekly `cargo update` (#12940) * chore(deps): weekly `cargo update` Updating git repository `https://github.com/rust-cli/rexpect` Updating git repository `https://github.com/paradigmxyz/solar.git` Skipping git submodule `https://github.com/argotorg/solidity.git` due to update strategy in .gitmodules Updating git repository `https://github.com/tempoxyz/tempo` Updating git repository `https://github.com/paradigmxyz/reth` Locking 71 packages to latest compatible versions Updating alloy-chains v0.2.23 -> v0.2.24 Updating alloy-consensus v1.1.3 -> v1.2.1 Updating alloy-consensus-any v1.1.3 -> v1.2.1 Updating alloy-contract v1.1.3 -> v1.2.1 Updating alloy-dyn-abi v1.5.1 -> v1.5.2 Updating alloy-eip5792 v1.1.3 -> v1.2.1 Updating alloy-eips v1.1.3 -> v1.2.1 Updating alloy-ens v1.1.3 -> v1.2.1 Updating alloy-genesis v1.1.3 -> v1.2.1 Updating alloy-json-abi v1.5.1 -> v1.5.2 Updating alloy-json-rpc v1.1.3 -> v1.2.1 Updating alloy-network v1.1.3 -> v1.2.1 Updating alloy-network-primitives v1.1.3 -> v1.2.1 Updating alloy-primitives v1.5.1 -> v1.5.2 Updating alloy-provider v1.1.3 -> v1.2.1 Updating alloy-pubsub v1.1.3 -> v1.2.1 Updating alloy-rpc-client v1.1.3 -> v1.2.1 Updating alloy-rpc-types v1.1.3 -> v1.2.1 Updating alloy-rpc-types-anvil v1.1.3 -> v1.2.1 Updating alloy-rpc-types-any v1.1.3 -> v1.2.1 Updating alloy-rpc-types-beacon v1.1.3 -> v1.2.1 Updating alloy-rpc-types-debug v1.1.3 -> v1.2.1 Updating alloy-rpc-types-engine v1.1.3 -> v1.2.1 Updating alloy-rpc-types-eth v1.1.3 -> v1.2.1 Updating alloy-rpc-types-trace v1.1.3 -> v1.2.1 Updating alloy-rpc-types-txpool v1.1.3 -> v1.2.1 Updating alloy-serde v1.1.3 -> v1.2.1 Updating alloy-signer v1.1.3 -> v1.2.1 Updating alloy-signer-aws v1.1.3 -> v1.2.1 Updating alloy-signer-gcp v1.1.3 -> v1.2.1 Updating alloy-signer-ledger v1.1.3 -> v1.2.1 Updating alloy-signer-local v1.1.3 -> v1.2.1 Updating alloy-signer-trezor v1.1.3 -> v1.2.1 Updating alloy-signer-turnkey v1.1.3 -> v1.2.1 Updating alloy-sol-macro v1.5.1 -> v1.5.2 Updating alloy-sol-macro-expander v1.5.1 -> v1.5.2 Updating alloy-sol-macro-input v1.5.1 -> v1.5.2 Updating alloy-sol-type-parser v1.5.1 -> v1.5.2 Updating alloy-sol-types v1.5.1 -> v1.5.2 Updating alloy-transport v1.1.3 -> v1.2.1 Updating alloy-transport-http v1.1.3 -> v1.2.1 Updating alloy-transport-ipc v1.1.3 -> v1.2.1 Updating alloy-transport-ws v1.1.3 -> v1.2.1 Updating alloy-trie v0.9.1 -> v0.9.2 Updating alloy-tx-macros v1.1.3 -> v1.2.1 Unchanged annotate-snippets v0.12.5 (available: v0.12.10) Unchanged anstyle-svg v0.1.11 (available: v0.1.12) Downgrading aws-smithy-runtime v1.9.6 -> v1.9.5 Updating axum-core v0.5.5 -> v0.5.6 Updating cc v1.2.50 -> v1.2.51 Updating derive_more v2.1.0 -> v2.1.1 Updating derive_more-impl v2.1.0 -> v2.1.1 Updating dtoa v1.0.10 -> v1.0.11 Updating find-msvc-tools v0.1.5 -> v0.1.6 Unchanged generic-array v0.14.7 (available: v0.14.9) Unchanged icu_collections v2.0.0 (available: v2.1.1) Unchanged icu_normalizer v2.0.1 (available: v2.1.1) Unchanged icu_normalizer_data v2.0.0 (available: v2.1.1) Unchanged icu_properties v2.0.2 (available: v2.1.2) Unchanged icu_properties_data v2.0.1 (available: v2.1.2) Unchanged idna_adapter v1.1.0 (available: v1.2.1) Updating itoa v1.0.15 -> v1.0.17 Updating jiff v0.2.16 -> v0.2.17 Updating jiff-static v0.2.16 -> v0.2.17 Updating libredox v0.1.11 -> v0.1.12 Updating libz-rs-sys v0.5.4 -> v0.5.5 Unchanged matchit v0.8.4 (available: v0.8.6) Unchanged mdbook v0.4.52 (available: v0.5.2) Updating portable-atomic v1.12.0 -> v1.13.0 Updating proc-macro2 v1.0.103 -> v1.0.104 Unchanged protobuf v3.3.0 (available: v3.7.2) Unchanged protobuf-support v3.3.0 (available: v3.7.2) Unchanged rand v0.8.5 (available: v0.9.2) Unchanged ratatui v0.29.0 (available: v0.30.0) Updating reqwest v0.12.26 -> v0.12.28 Updating ruint v1.17.0 -> v1.17.1 Updating rustix v1.1.2 -> v1.1.3 Updating ryu v1.0.21 -> v1.0.22 Updating schemars v1.1.0 -> v1.2.0 Updating schemars_derive v1.1.0 -> v1.2.0 Updating serde_json v1.0.145 -> v1.0.148 Updating signal-hook-registry v1.4.7 -> v1.4.8 Updating syn-solidity v1.5.1 -> v1.5.2 Updating tempfile v3.23.0 -> v3.24.0 Unchanged trezor-client v0.1.4 (available: v0.1.5) Unchanged unicode-width v0.2.0 (available: v0.2.2) Unchanged vergen v8.3.2 (available: v9.0.6) Updating zlib-rs v0.5.4 -> v0.5.5 Adding zmij v1.0.0 note: to see how you depend on a package, run `cargo tree --invert @` * touchups * touchups --------- Co-authored-by: mattsse <19890894+mattsse@users.noreply.github.com> Co-authored-by: Matthias Seitz * Update flake.lock (#12939) flake.lock: Update Flake lock file updates: • Updated input 'fenix': 'github:nix-community/fenix/16642c5' (2025-12-20) → 'github:nix-community/fenix/3479aaf' (2025-12-27) • Updated input 'fenix/rust-analyzer-src': 'github:rust-lang/rust-analyzer/ea1d299' (2025-12-18) → 'github:rust-lang/rust-analyzer/8c5a68e' (2025-12-26) • Updated input 'nixpkgs': 'github:NixOS/nixpkgs/7d853e5' (2025-12-19) → 'github:NixOS/nixpkgs/3edc4a3' (2025-12-27) Co-authored-by: github-actions[bot] Co-authored-by: DaniPopes <57450786+DaniPopes@users.noreply.github.com> * fix(chisel): uninitalized variables (#12937) * chore(deps): bump Swatinem/rust-cache from 2.8.1 to 2.8.2 (#12919) Bumps [Swatinem/rust-cache](https://github.com/swatinem/rust-cache) from 2.8.1 to 2.8.2. - [Release notes](https://github.com/swatinem/rust-cache/releases) - [Changelog](https://github.com/Swatinem/rust-cache/blob/master/CHANGELOG.md) - [Commits](https://github.com/swatinem/rust-cache/compare/f13886b937689c021905a6b90929199931d60db1...779680da715d629ac1d338a641029a2f4372abb5) --- updated-dependencies: - dependency-name: Swatinem/rust-cache dependency-version: 2.8.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: zerosnacks <95942363+zerosnacks@users.noreply.github.com> * chore(deps): bump peter-evans/create-pull-request from 7.0.11 to 8.0.0 (#12918) Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 7.0.11 to 8.0.0. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/22a9089034f40e5a961c8808d113e2c98fb63676...98357b18bf14b5342f975ff684046ec3b2a07725) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-version: 8.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: grandizzy <38490174+grandizzy@users.noreply.github.com> * chore: sepolia rpc url (#12945) chore: sepolia rpc url private * chore(deps): bump crate-ci/typos from 1.40.0 to 1.40.1 (#12949) Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.40.0 to 1.40.1. - [Release notes](https://github.com/crate-ci/typos/releases) - [Changelog](https://github.com/crate-ci/typos/blob/master/CHANGELOG.md) - [Commits](https://github.com/crate-ci/typos/compare/2d0ce569feab1f8752f1dde43cc2f2aa53236e06...1a319b54cc9e3b333fed6a5c88ba1a90324da514) --- updated-dependencies: - dependency-name: crate-ci/typos dependency-version: 1.40.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump DeterminateSystems/determinate-nix-action from 3.15.0 to 3.15.1 (#12950) chore(deps): bump DeterminateSystems/determinate-nix-action Bumps [DeterminateSystems/determinate-nix-action](https://github.com/determinatesystems/determinate-nix-action) from 3.15.0 to 3.15.1. - [Release notes](https://github.com/determinatesystems/determinate-nix-action/releases) - [Commits](https://github.com/determinatesystems/determinate-nix-action/compare/95732e95d70db3ba1e0adc26a63c5e0375aba78c...1d699fc25db3f9e079cd2f168ca007a4183389be) --- updated-dependencies: - dependency-name: DeterminateSystems/determinate-nix-action dependency-version: 3.15.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump taiki-e/install-action from 2.65.1 to 2.65.7 (#12951) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.65.1 to 2.65.7. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/b9c5db3aef04caffaf95a1d03931de10fb2a140f...4c6723ec9c638cccae824b8957c5085b695c8085) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-version: 2.65.7 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * fix(config): err on unknown profile (#12946) * test: remove duplicate Issue2851 test (#12953) * chore(cheats): make sign(Wallet) pure (#12912) * chore(cheats): make sign(Wallet) pure * ignore --------- Co-authored-by: Matthias Seitz Co-authored-by: grandizzy <38490174+grandizzy@users.noreply.github.com> * fix(evm): use timestamp-based blob base fee calculation (#12959) * fix(evm): use timestamp-based blob base fee calculation * chore: use patch * Now BPO1 is default * bump to hardforks to 0.4.7 --------- Co-authored-by: Matthias Seitz * fix(config): reject bare versions in compilation restrictions (#12955) fmt Co-authored-by: tefyosL-sol * Revert "fix(config): err on unknown profile (#12946)" (#12964) This reverts commit 6ff4b52e2e572e93d0cd81591b1bd0e6ad9ed507. * fix(anvil): use B256 instead of TxHash for block hash parameters (#12961) Update mod.rs * Update crates/config/src/compilation.rs Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --------- Signed-off-by: dependabot[bot] Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: Matthias Seitz Co-authored-by: Claude Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: mattsse <19890894+mattsse@users.noreply.github.com> Co-authored-by: github-actions[bot] Co-authored-by: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: zerosnacks <95942363+zerosnacks@users.noreply.github.com> Co-authored-by: grandizzy <38490174+grandizzy@users.noreply.github.com> Co-authored-by: cakevm Co-authored-by: Theodore Solis Co-authored-by: tefyosL-sol Co-authored-by: Desant pivo Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> --- .github/workflows/bump-forge-std.yml | 2 +- .github/workflows/ci.yml | 12 +- .github/workflows/docs.yml | 2 +- .github/workflows/nix.yml | 4 +- .github/workflows/test.yml | 5 +- Cargo.lock | 312 ++++++++++++----------- Cargo.toml | 4 +- crates/anvil/core/src/eth/mod.rs | 4 +- crates/anvil/src/eth/api.rs | 4 +- crates/anvil/src/eth/backend/fork.rs | 4 +- crates/anvil/src/eth/backend/mem/mod.rs | 12 +- crates/anvil/src/tasks/mod.rs | 4 +- crates/anvil/tests/it/anvil_api.rs | 2 +- crates/anvil/tests/it/api.rs | 4 +- crates/cheatcodes/assets/cheatcodes.json | 8 +- crates/cheatcodes/spec/src/vm.rs | 4 +- crates/chisel/src/dispatcher.rs | 2 - crates/chisel/src/executor.rs | 6 +- crates/chisel/tests/it/repl/mod.rs | 62 +++-- crates/config/src/compilation.rs | 33 ++- crates/config/src/lib.rs | 53 ++++ crates/evm/core/src/backend/mod.rs | 4 +- crates/forge/tests/cli/test_cmd/mod.rs | 27 ++ crates/linking/src/lib.rs | 1 + crates/test-utils/src/rpc.rs | 7 + deny.toml | 2 + flake.lock | 18 +- testdata/default/repros/Issue2851.t.sol | 30 --- testdata/utils/Vm.sol | 4 +- 29 files changed, 372 insertions(+), 264 deletions(-) delete mode 100644 testdata/default/repros/Issue2851.t.sol diff --git a/.github/workflows/bump-forge-std.yml b/.github/workflows/bump-forge-std.yml index 2fb3e8a9a536f..00109defa89b1 100644 --- a/.github/workflows/bump-forge-std.yml +++ b/.github/workflows/bump-forge-std.yml @@ -23,7 +23,7 @@ jobs: - name: Fetch and update forge-std tag run: curl 'https://api.github.com/repos/foundry-rs/forge-std/tags' | jq '.[0].commit.sha' -jr > testdata/forge-std-rev - name: Create pull request - uses: peter-evans/create-pull-request@22a9089034f40e5a961c8808d113e2c98fb63676 # v7 + uses: peter-evans/create-pull-request@98357b18bf14b5342f975ff684046ec3b2a07725 # v7 with: commit-message: "chore: bump forge-std version used for tests" title: "chore(tests): bump forge-std version" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 578a95c4738cc..ac58f9560d0f8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -46,7 +46,7 @@ jobs: toolchain: stable - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 - uses: mozilla-actions/sccache-action@7d986dd989559c6ecdb630a3fd2557667be217ad # v0.0.9 - - uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # v2 + - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2 - run: cargo test --workspace --doc typos: @@ -58,7 +58,7 @@ jobs: - uses: actions/checkout@v6 with: persist-credentials: false - - uses: crate-ci/typos@2d0ce569feab1f8752f1dde43cc2f2aa53236e06 # v1 + - uses: crate-ci/typos@1a319b54cc9e3b333fed6a5c88ba1a90324da514 # v1 shellcheck: runs-on: depot-ubuntu-latest @@ -88,7 +88,7 @@ jobs: components: clippy - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 - uses: mozilla-actions/sccache-action@7d986dd989559c6ecdb630a3fd2557667be217ad # v0.0.9 - - uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # v2 + - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2 - run: cargo clippy --workspace --all-targets --all-features env: RUSTFLAGS: -Dwarnings @@ -122,7 +122,7 @@ jobs: toolchain: stable - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 - uses: mozilla-actions/sccache-action@7d986dd989559c6ecdb630a3fd2557667be217ad # v0.0.9 - - uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # v2 + - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2 - name: forge fmt shell: bash run: ./.github/scripts/format.sh --check @@ -140,11 +140,11 @@ jobs: with: toolchain: stable - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 - - uses: taiki-e/install-action@b9c5db3aef04caffaf95a1d03931de10fb2a140f # v2 + - uses: taiki-e/install-action@4c6723ec9c638cccae824b8957c5085b695c8085 # v2 with: tool: cargo-hack - uses: mozilla-actions/sccache-action@7d986dd989559c6ecdb630a3fd2557667be217ad # v0.0.9 - - uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # v2 + - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2 - run: cargo hack check deny: diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 04a99b63626ee..2ace7a6c6fcf1 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -32,7 +32,7 @@ jobs: toolchain: nightly - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 - uses: mozilla-actions/sccache-action@7d986dd989559c6ecdb630a3fd2557667be217ad # v0.0.9 - - uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # v2 + - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2 - name: Build documentation run: cargo doc --workspace --all-features --no-deps --document-private-items env: diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index 2c51ee2d99fbd..7082dc5dff403 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -19,7 +19,7 @@ jobs: contents: write pull-requests: write steps: - - uses: DeterminateSystems/determinate-nix-action@95732e95d70db3ba1e0adc26a63c5e0375aba78c # v3 + - uses: DeterminateSystems/determinate-nix-action@1d699fc25db3f9e079cd2f168ca007a4183389be # v3 - uses: actions/checkout@v6 with: persist-credentials: false @@ -38,7 +38,7 @@ jobs: permissions: contents: read steps: - - uses: DeterminateSystems/determinate-nix-action@95732e95d70db3ba1e0adc26a63c5e0375aba78c # v3 + - uses: DeterminateSystems/determinate-nix-action@1d699fc25db3f9e079cd2f168ca007a4183389be # v3 - uses: actions/checkout@v6 with: persist-credentials: false diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6d2e9ce09250e..79f4dfc4431db 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -66,7 +66,7 @@ jobs: toolchain: stable target: ${{ matrix.target }} - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 - - uses: taiki-e/install-action@b9c5db3aef04caffaf95a1d03931de10fb2a140f # v2 + - uses: taiki-e/install-action@4c6723ec9c638cccae824b8957c5085b695c8085 # v2 with: tool: nextest @@ -102,7 +102,7 @@ jobs: restore-keys: | ${{ runner.os }}-foundry-${{ matrix.name }}- - uses: mozilla-actions/sccache-action@7d986dd989559c6ecdb630a3fd2557667be217ad # v0.0.9 - - uses: Swatinem/rust-cache@f13886b937689c021905a6b90929199931d60db1 # v2 + - uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2 - name: Setup Git config run: | git config --global user.name "GitHub Actions Bot" @@ -115,4 +115,5 @@ jobs: WS_ARCHIVE_URLS: ${{ secrets.WS_ARCHIVE_URLS }} ETHERSCAN_KEY: ${{ secrets.ETHERSCAN_API_KEY }} ARBITRUM_RPC: ${{ secrets.ARBITRUM_RPC }} + ETH_SEPOLIA_RPC: ${{ secrets.ETH_SEPOLIA_RPC }} run: cargo nextest run ${{ matrix.flags }} diff --git a/Cargo.lock b/Cargo.lock index 0db46ec2c09e8..f19b33e2859ae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -67,9 +67,9 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "alloy-chains" -version = "0.2.23" +version = "0.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35d744058a9daa51a8cf22a3009607498fcf82d3cf4c5444dd8056cdf651f471" +checksum = "b163ff4acf0eac29af05a911397cc418a76e153467b859398adc26cb9335a611" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -80,9 +80,9 @@ dependencies = [ [[package]] name = "alloy-consensus" -version = "1.1.3" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e318e25fb719e747a7e8db1654170fc185024f3ed5b10f86c08d448a912f6e2" +checksum = "f3dcd2b4e208ce5477de90ccdcbd4bde2c8fb06af49a443974e92bb8f2c5e93f" dependencies = [ "alloy-eips", "alloy-primitives", @@ -107,9 +107,9 @@ dependencies = [ [[package]] name = "alloy-consensus-any" -version = "1.1.3" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "364380a845193a317bcb7a5398fc86cdb66c47ebe010771dde05f6869bf9e64a" +checksum = "ee5655f234985f5ab1e31bef7e02ed11f0a899468cf3300e061e1b96e9e11de0" dependencies = [ "alloy-consensus", "alloy-eips", @@ -121,9 +121,9 @@ dependencies = [ [[package]] name = "alloy-contract" -version = "1.1.3" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d39c80ffc806f27a76ed42f3351a455f3dc4f81d6ff92c8aad2cf36b7d3a34" +checksum = "7f01b6d8e5b4f3222aaf7f18613a7292e2fbc9163fe120649cd1b078ca534349" dependencies = [ "alloy-consensus", "alloy-dyn-abi", @@ -144,9 +144,9 @@ dependencies = [ [[package]] name = "alloy-dyn-abi" -version = "1.5.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d48a9101f4a67c22fae57489f1ddf3057b8ab4a368d8eac3be088b6e9d9c9d9" +checksum = "369f5707b958927176265e8a58627fc6195e5dfa5c55689396e68b241b3a72e6" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -188,9 +188,9 @@ dependencies = [ [[package]] name = "alloy-eip5792" -version = "1.1.3" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deb56700a502913fa9d40367e8f8c77720b043447c7763305f4ab582d713e36d" +checksum = "cdb31eba85ca1ac2f9df9170ffda56b470816b899c8be577a5b4c6a830368682" dependencies = [ "alloy-primitives", "alloy-serde", @@ -215,9 +215,9 @@ dependencies = [ [[package]] name = "alloy-eips" -version = "1.1.3" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c4d7c5839d9f3a467900c625416b24328450c65702eb3d8caff8813e4d1d33" +checksum = "6847d641141b92a1557094aa6c236cbe49c06fb24144d4a21fe6acb970c15888" dependencies = [ "alloy-eip2124", "alloy-eip2930", @@ -240,9 +240,9 @@ dependencies = [ [[package]] name = "alloy-ens" -version = "1.1.3" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a171486ee60b6f98e12451b1eddd1458bc21571f3829f75fcf12bb16ae48e59" +checksum = "9ddbb0d31df814ea588fc61034c3f3d21dc3678e65e26a50fff21fd35b4d0d3b" dependencies = [ "alloy-contract", "alloy-primitives", @@ -276,9 +276,9 @@ dependencies = [ [[package]] name = "alloy-genesis" -version = "1.1.3" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ba4b1be0988c11f0095a2380aa596e35533276b8fa6c9e06961bbfe0aebcac5" +checksum = "fe3192fca2eb0b0c4b122b3c2d8254496b88a4e810558dddd3ea2f30ad9469df" dependencies = [ "alloy-eips", "alloy-primitives", @@ -291,9 +291,9 @@ dependencies = [ [[package]] name = "alloy-hardforks" -version = "0.4.5" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d9a33550fc21fd77a3f8b63e99969d17660eec8dcc50a95a80f7c9964f7680b" +checksum = "83ba208044232d14d4adbfa77e57d6329f51bc1acc21f5667bb7db72d88a0831" dependencies = [ "alloy-chains", "alloy-eip2124", @@ -304,9 +304,9 @@ dependencies = [ [[package]] name = "alloy-json-abi" -version = "1.5.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9914c147bb9b25f440eca68a31dc29f5c22298bfa7754aa802965695384122b0" +checksum = "84e3cf01219c966f95a460c95f1d4c30e12f6c18150c21a30b768af2a2a29142" dependencies = [ "alloy-primitives", "alloy-sol-type-parser", @@ -316,9 +316,9 @@ dependencies = [ [[package]] name = "alloy-json-rpc" -version = "1.1.3" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f72cf87cda808e593381fb9f005ffa4d2475552b7a6c5ac33d087bf77d82abd0" +checksum = "d4ab3330e491053e9608b2a315f147357bb8acb9377a988c1203f2e8e2b296c9" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -331,9 +331,9 @@ dependencies = [ [[package]] name = "alloy-network" -version = "1.1.3" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12aeb37b6f2e61b93b1c3d34d01ee720207c76fe447e2a2c217e433ac75b17f5" +checksum = "c1e22ff194b1e34b4defd1e257e3fe4dce0eee37451c7757a1510d6b23e7379a" dependencies = [ "alloy-consensus", "alloy-consensus-any", @@ -357,9 +357,9 @@ dependencies = [ [[package]] name = "alloy-network-primitives" -version = "1.1.3" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abd29ace62872083e30929cd9b282d82723196d196db589f3ceda67edcc05552" +checksum = "b8a6cbb9f431bdad294eebb5af9b293d6979e633bfe5468d1e87c1421a858265" dependencies = [ "alloy-consensus", "alloy-eips", @@ -388,9 +388,9 @@ dependencies = [ [[package]] name = "alloy-op-hardforks" -version = "0.4.5" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f96fb2fce4024ada5b2c11d4076acf778a0d3e4f011c6dfd2ffce6d0fcf84ee9" +checksum = "6472c610150c4c4c15be9e1b964c9b78068f933bda25fb9cdf09b9ac2bb66f36" dependencies = [ "alloy-chains", "alloy-hardforks", @@ -400,9 +400,9 @@ dependencies = [ [[package]] name = "alloy-primitives" -version = "1.5.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7db950a29746be9e2f2c6288c8bd7a6202a81f999ce109a2933d2379970ec0fa" +checksum = "f6a0fb18dd5fb43ec5f0f6a20be1ce0287c79825827de5744afaa6c957737c33" dependencies = [ "alloy-rlp", "arbitrary", @@ -431,9 +431,9 @@ dependencies = [ [[package]] name = "alloy-provider" -version = "1.1.3" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b710636d7126e08003b8217e24c09f0cca0b46d62f650a841736891b1ed1fc1" +checksum = "3f5dde1abc3d582e53d139904fcdd8b2103f0bd03e8f2acb4292edbbaeaa7e6e" dependencies = [ "alloy-chains", "alloy-consensus", @@ -476,9 +476,9 @@ dependencies = [ [[package]] name = "alloy-pubsub" -version = "1.1.3" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdd4c64eb250a18101d22ae622357c6b505e158e9165d4c7974d59082a600c5e" +checksum = "acbfe0a3c553a027f722185fb574124d205147fffb309cae52d0a2094f076887" dependencies = [ "alloy-json-rpc", "alloy-primitives", @@ -520,9 +520,9 @@ dependencies = [ [[package]] name = "alloy-rpc-client" -version = "1.1.3" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0882e72d2c1c0c79dcf4ab60a67472d3f009a949f774d4c17d0bdb669cfde05" +checksum = "5a94bdef2710322c6770be08689fee0878c2ad75615b8fc40e05d7f3c9618c0b" dependencies = [ "alloy-json-rpc", "alloy-primitives", @@ -546,9 +546,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types" -version = "1.1.3" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39cf1398cb33aacb139a960fa3d8cf8b1202079f320e77e952a0b95967bf7a9f" +checksum = "811a573c8080e1b492d488e6a240ec5dd7677d7167e91ce9cb4d0ec1fcac8027" dependencies = [ "alloy-primitives", "alloy-rpc-types-anvil", @@ -562,9 +562,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-anvil" -version = "1.1.3" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3ce4c24e416bd0f17fceeb2f26cd8668df08fe19e1dc02f9d41c3b8ed1e93e0" +checksum = "838ca94be532a929f27961851000ec8bbbaeb06e2a2bcca44fac7855a2fe0f6f" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", @@ -574,9 +574,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-any" -version = "1.1.3" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a63fb40ed24e4c92505f488f9dd256e2afaed17faa1b7a221086ebba74f4122" +checksum = "12df0b34551ca2eab8ec83b56cb709ee5da991737282180d354a659b907f00dc" dependencies = [ "alloy-consensus-any", "alloy-rpc-types-eth", @@ -585,9 +585,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-beacon" -version = "1.1.3" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16633087e23d8d75161c3a59aa183203637b817a5a8d2f662f612ccb6d129af0" +checksum = "32598a2443750a2e884c1b48efccaeeaae75e7eb4e0f13df9146b78107b4c301" dependencies = [ "alloy-eips", "alloy-primitives", @@ -601,9 +601,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-debug" -version = "1.1.3" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4936f579d9d10eae01772b2ab3497f9d568684f05f26f8175e12f9a1a2babc33" +checksum = "6c49a3a168a5bf18f1cf7ed5723a650aebe714edf7665b53dacf5707716733d0" dependencies = [ "alloy-primitives", "derive_more", @@ -613,9 +613,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-engine" -version = "1.1.3" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c60bdce3be295924122732b7ecd0b2495ce4790bedc5370ca7019c08ad3f26e" +checksum = "ffe16cd1dea6089902ec609e04261a9ae6d11ec66005ba24c1f97f0eefbc0fa9" dependencies = [ "alloy-consensus", "alloy-eips", @@ -633,9 +633,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-eth" -version = "1.1.3" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9eae0c7c40da20684548cbc8577b6b7447f7bf4ddbac363df95e3da220e41e72" +checksum = "b7f9f130511b8632686dfe6f9909b38d7ae4c68de3ce17d28991400646a39b25" dependencies = [ "alloy-consensus", "alloy-consensus-any", @@ -654,9 +654,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-trace" -version = "1.1.3" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef206a4b8d436fbb7cf2e6a61c692d11df78f9382becc3c9a283bd58e64f0583" +checksum = "cafe859944638c5d57d1a3a0034cdb5d07c98c37de8adce5508f28834acf958f" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", @@ -668,9 +668,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-txpool" -version = "1.1.3" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecb5a795264a02222f9534435b8f40dcbd88de8e9d586647884aae24f389ebf2" +checksum = "afaa06544e36f223b99b1415a12911230fd527994f020736c3c7950d5080208e" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", @@ -680,9 +680,9 @@ dependencies = [ [[package]] name = "alloy-serde" -version = "1.1.3" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0df1987ed0ff2d0159d76b52e7ddfc4e4fbddacc54d2fbee765e0d14d7c01b5" +checksum = "067b718d2e6ac1bb889341fcc7a250cfa49bcd3ba4f23923f1c1eb1f2b10cb7c" dependencies = [ "alloy-primitives", "serde", @@ -691,9 +691,9 @@ dependencies = [ [[package]] name = "alloy-signer" -version = "1.1.3" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff69deedee7232d7ce5330259025b868c5e6a52fa8dffda2c861fb3a5889b24" +checksum = "acff6b251740ef473932386d3b71657d3825daebf2217fb41a7ef676229225d4" dependencies = [ "alloy-dyn-abi", "alloy-primitives", @@ -708,9 +708,9 @@ dependencies = [ [[package]] name = "alloy-signer-aws" -version = "1.1.3" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc8784b7567d5cfdad7450c5c71ddbdc12b288b82ea559be7a5363c28f774210" +checksum = "a4111255269e2d96b7e064ffa98f94ebc51c8e18d43501a10808c316e6d5a4d6" dependencies = [ "alloy-consensus", "alloy-network", @@ -727,9 +727,9 @@ dependencies = [ [[package]] name = "alloy-signer-gcp" -version = "1.1.3" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70059cb6f08c225be3840f8104573fd9342ca29117a735ea09ed8ee1be09fb9f" +checksum = "b3fe5d26c2e1144aa89d65a0f1d1faec4dbf4c3ea1f7375888274c6609de2234" dependencies = [ "alloy-consensus", "alloy-network", @@ -745,9 +745,9 @@ dependencies = [ [[package]] name = "alloy-signer-ledger" -version = "1.1.3" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a54e01fb2228c993c9ef7735043bb22c88a84502628fae820d6469c3bebddb84" +checksum = "018fe424516f3bad2aefca5ee556a9c75301d68ab5377e296f85d33d6dc446c0" dependencies = [ "alloy-consensus", "alloy-dyn-abi", @@ -765,9 +765,9 @@ dependencies = [ [[package]] name = "alloy-signer-local" -version = "1.1.3" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72cfe0be3ec5a8c1a46b2e5a7047ed41121d360d97f4405bb7c1c784880c86cb" +checksum = "c9129ef31975d987114c27c9930ee817cf3952355834d47f2fdf4596404507e8" dependencies = [ "alloy-consensus", "alloy-network", @@ -785,9 +785,9 @@ dependencies = [ [[package]] name = "alloy-signer-trezor" -version = "1.1.3" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "119c750dd3d2158c57ab14711dca06cd6dc5db657bd16e6ab46ed11112187958" +checksum = "af231a5e9b07e54cd3142ad51bd07cbb95b4ccb4db991897a0ab9e7ed052286f" dependencies = [ "alloy-consensus", "alloy-network", @@ -802,9 +802,9 @@ dependencies = [ [[package]] name = "alloy-signer-turnkey" -version = "1.1.3" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd65beb3a838bff2e528e2ac4f0cf14f55893c4f0bc67c8339f2752b3d144022" +checksum = "1dae31a1578b3dedbc7c07aa5376d399adcf883caca7fdd56151b7618df72634" dependencies = [ "alloy-consensus", "alloy-network", @@ -818,9 +818,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro" -version = "1.5.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3b96d5f5890605ba9907ce1e2158e2701587631dc005bfa582cf92dd6f21147" +checksum = "09eb18ce0df92b4277291bbaa0ed70545d78b02948df756bbd3d6214bf39a218" dependencies = [ "alloy-sol-macro-expander", "alloy-sol-macro-input", @@ -832,9 +832,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro-expander" -version = "1.5.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8247b7cca5cde556e93f8b3882b01dbd272f527836049083d240c57bf7b4c15" +checksum = "95d9fa2daf21f59aa546d549943f10b5cce1ae59986774019fbedae834ffe01b" dependencies = [ "alloy-json-abi", "alloy-sol-macro-input", @@ -851,9 +851,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro-input" -version = "1.5.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cd54f38512ac7bae10bbc38480eefb1b9b398ca2ce25db9cc0c048c6411c4f1" +checksum = "9396007fe69c26ee118a19f4dee1f5d1d6be186ea75b3881adf16d87f8444686" dependencies = [ "alloy-json-abi", "const-hex", @@ -869,9 +869,9 @@ dependencies = [ [[package]] name = "alloy-sol-type-parser" -version = "1.5.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "444b09815b44899564566d4d56613d14fa9a274b1043a021f00468568752f449" +checksum = "af67a0b0dcebe14244fc92002cd8d96ecbf65db4639d479f5fcd5805755a4c27" dependencies = [ "serde", "winnow", @@ -879,9 +879,9 @@ dependencies = [ [[package]] name = "alloy-sol-types" -version = "1.5.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc1038284171df8bfd48befc0c7b78f667a7e2be162f45f07bd1c378078ebe58" +checksum = "09aeea64f09a7483bdcd4193634c7e5cf9fd7775ee767585270cd8ce2d69dc95" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -891,9 +891,9 @@ dependencies = [ [[package]] name = "alloy-transport" -version = "1.1.3" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be98b07210d24acf5b793c99b759e9a696e4a2e67593aec0487ae3b3e1a2478c" +checksum = "bec1fb08ee484e615f24867c0b154fff5722bb00176102a16868c6532b7c3623" dependencies = [ "alloy-json-rpc", "auto_impl", @@ -914,9 +914,9 @@ dependencies = [ [[package]] name = "alloy-transport-http" -version = "1.1.3" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4198a1ee82e562cab85e7f3d5921aab725d9bd154b6ad5017f82df1695877c97" +checksum = "64b722073c76f2de7e118d546ee1921c50710f97feb32aed50db94cfa5b663e1" dependencies = [ "alloy-json-rpc", "alloy-transport", @@ -929,9 +929,9 @@ dependencies = [ [[package]] name = "alloy-transport-ipc" -version = "1.1.3" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8db249779ebc20dc265920c7e706ed0d31dbde8627818d1cbde60919b875bb0" +checksum = "bdedcf401aab4b96d8b5e6638b79d04a6afb96c0bfcb50a2324fbadfe65c47b3" dependencies = [ "alloy-json-rpc", "alloy-pubsub", @@ -949,15 +949,14 @@ dependencies = [ [[package]] name = "alloy-transport-ws" -version = "1.1.3" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ad2344a12398d7105e3722c9b7a7044ea837128e11d453604dec6e3731a86e2" +checksum = "942210908f0c56941097f5653a5f334546940e6fd9073495b257e52216469feb" dependencies = [ "alloy-pubsub", "alloy-transport", "futures", "http 1.4.0", - "rustls", "serde_json", "tokio", "tokio-tungstenite 0.26.2", @@ -967,9 +966,9 @@ dependencies = [ [[package]] name = "alloy-trie" -version = "0.9.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3412d52bb97c6c6cc27ccc28d4e6e8cf605469101193b50b0bd5813b1f990b5" +checksum = "2b77b56af09ead281337d06b1d036c88e2dc8a2e45da512a532476dbee94912b" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -983,9 +982,9 @@ dependencies = [ [[package]] name = "alloy-tx-macros" -version = "1.1.3" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "333544408503f42d7d3792bfc0f7218b643d968a03d2c0ed383ae558fb4a76d0" +checksum = "04950a13cc4209d8e9b78f306e87782466bad8538c94324702d061ff03e211c9" dependencies = [ "darling 0.21.3", "proc-macro2", @@ -1957,9 +1956,9 @@ dependencies = [ [[package]] name = "aws-smithy-runtime" -version = "1.9.6" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65fda37911905ea4d3141a01364bc5509a0f32ae3f3b22d6e330c0abfb62d247" +checksum = "a392db6c583ea4a912538afb86b7be7c5d8887d91604f50eb55c262ee1b4a5f5" dependencies = [ "aws-smithy-async", "aws-smithy-http", @@ -2080,9 +2079,9 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.5.5" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59446ce19cd142f8833f856eb31f3eb097812d1479ab224f54d72428ca21ea22" +checksum = "08c78f31d7b1291f7ee735c1c6780ccde7785daae9a9206026862dab7d8792d1" dependencies = [ "bytes", "futures-core", @@ -2652,9 +2651,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.50" +version = "1.2.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f50d563227a1c37cc0a263f64eca3334388c01c5e4c4861a9def205c614383c" +checksum = "7a0aeaff4ff1a90589618835a598e545176939b97874f7abc7851caa0618f203" dependencies = [ "find-msvc-tools", "jobserver", @@ -3292,7 +3291,7 @@ dependencies = [ "document-features", "mio", "parking_lot", - "rustix 1.1.2", + "rustix 1.1.3", "signal-hook", "signal-hook-mio", "winapi", @@ -3556,18 +3555,18 @@ dependencies = [ [[package]] name = "derive_more" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10b768e943bed7bf2cab53df09f4bc34bfd217cdb57d971e769874c9a6710618" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" dependencies = [ "derive_more-impl", ] [[package]] name = "derive_more-impl" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d286bfdaf75e988b4a78e013ecd79c581e06399ab53fbacd2d916c2f904f30b" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" dependencies = [ "convert_case", "proc-macro2", @@ -3688,9 +3687,9 @@ checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1" [[package]] name = "dtoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6add3b8cff394282be81f3fc1a0605db594ed69890078ca6e2cab1c408bcf04" +checksum = "4c3cf4824e2d5f025c7b531afcb2325364084a16806f6d47fbc1f5fbd9960590" [[package]] name = "dtoa-short" @@ -4107,7 +4106,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce92ff622d6dadf7349484f42c93271a0d49b7cc4d466a936405bacbe10aa78" dependencies = [ "cfg-if", - "rustix 1.1.2", + "rustix 1.1.3", "windows-sys 0.59.0", ] @@ -4149,9 +4148,9 @@ dependencies = [ [[package]] name = "find-msvc-tools" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" +checksum = "645cbb3a84e60b7531617d5ae4e57f7e27308f6445f5abf653209ea76dec8dff" [[package]] name = "fixed-hash" @@ -4554,7 +4553,7 @@ version = "1.5.1" dependencies = [ "alloy-sol-types", "foundry-macros", - "schemars 1.1.0", + "schemars 1.2.0", "serde", "serde_json", ] @@ -6189,15 +6188,15 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" [[package]] name = "jiff" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49cce2b81f2098e7e3efc35bc2e0a6b7abec9d34128283d7a26fa8f32a6dbb35" +checksum = "a87d9b8105c23642f50cbbae03d1f75d8422c5cb98ce7ee9271f7ff7505be6b8" dependencies = [ "jiff-static", "log", @@ -6208,9 +6207,9 @@ dependencies = [ [[package]] name = "jiff-static" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "980af8b43c3ad5d8d349ace167ec8170839f753a42d233ba19e08afe1850fa69" +checksum = "b787bebb543f8969132630c51fd0afab173a86c6abae56ff3b9e5e3e3f9f6e58" dependencies = [ "proc-macro2", "quote", @@ -6418,9 +6417,9 @@ dependencies = [ [[package]] name = "libredox" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df15f6eac291ed1cf25865b1ee60399f57e7c227e7f51bdbd4c5270396a9ed50" +checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" dependencies = [ "bitflags 2.10.0", "libc", @@ -6440,9 +6439,9 @@ dependencies = [ [[package]] name = "libz-rs-sys" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15413ef615ad868d4d65dce091cb233b229419c7c0c4bcaa746c0901c49ff39c" +checksum = "c10501e7805cee23da17c7790e59df2870c0d4043ec6d03f67d31e2b53e77415" dependencies = [ "zlib-rs", ] @@ -7670,9 +7669,9 @@ checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] name = "portable-atomic" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f59e70c4aef1e55797c2e8fd94a4f2a973fc972cfde0e0b05f683667b0cd39dd" +checksum = "f89776e4d69bb58bc6993e99ffa1d11f228b839984854c7daeb5d37f87cbe950" [[package]] name = "portable-atomic-util" @@ -7812,9 +7811,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.103" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +checksum = "9695f8df41bb4f3d222c95a67532365f569318332d03d5f3f67f37b20e6ebdf0" dependencies = [ "unicode-ident", ] @@ -8350,9 +8349,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.26" +version = "0.12.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b4c14b2d9afca6a60277086b0cc6a6ae0b568f6f7916c943a8cdc79f8be240f" +checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" dependencies = [ "base64 0.22.1", "bytes", @@ -9049,9 +9048,9 @@ dependencies = [ [[package]] name = "ruint" -version = "1.17.0" +version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a68df0380e5c9d20ce49534f292a36a7514ae21350726efe1865bdb1fa91d278" +checksum = "7f5befb5191be3584a4edaf63435e8ff92ffff622e711ca7e77f8f8f365a9df8" dependencies = [ "alloy-rlp", "arbitrary", @@ -9167,9 +9166,9 @@ dependencies = [ [[package]] name = "rustix" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" +checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" dependencies = [ "bitflags 2.10.0", "errno", @@ -9270,9 +9269,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.21" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62049b2877bf12821e8f9ad256ee38fdc31db7387ec2d3b3f403024de2034aea" +checksum = "a50f4cf475b65d88e057964e0e9bb1f0aa9bbb2036dc65c64596b42932536984" [[package]] name = "ryu-js" @@ -9330,9 +9329,9 @@ dependencies = [ [[package]] name = "schemars" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9558e172d4e8533736ba97870c4b2cd63f84b382a3d6eb063da41b91cce17289" +checksum = "54e910108742c57a770f492731f99be216a52fadd361b06c8fb59d74ccc267d2" dependencies = [ "dyn-clone", "ref-cast", @@ -9343,9 +9342,9 @@ dependencies = [ [[package]] name = "schemars_derive" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301858a4023d78debd2353c7426dc486001bddc91ae31a76fb1f55132f7e2633" +checksum = "4908ad288c5035a8eb12cfdf0d49270def0a268ee162b75eeee0f85d155a7c45" dependencies = [ "proc-macro2", "quote", @@ -9570,16 +9569,16 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.145" +version = "1.0.148" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +checksum = "3084b546a1dd6289475996f182a22aba973866ea8e8b02c51d9f46b1336a22da" dependencies = [ "indexmap 2.12.1", "itoa", "memchr", - "ryu", "serde", "serde_core", + "zmij", ] [[package]] @@ -9635,7 +9634,7 @@ dependencies = [ "indexmap 1.9.3", "indexmap 2.12.1", "schemars 0.9.0", - "schemars 1.1.0", + "schemars 1.2.0", "serde_core", "serde_json", "serde_with_macros", @@ -9750,10 +9749,11 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.7" +version = "1.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7664a098b8e616bdfcc2dc0e9ac44eb231eedf41db4e9fe95d8d32ec728dedad" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" dependencies = [ + "errno", "libc", ] @@ -10349,9 +10349,9 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "1.5.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6b1d2e2059056b66fec4a6bb2b79511d5e8d76196ef49c38996f4b48db7662f" +checksum = "5f92d01b5de07eaf324f7fca61cc6bd3d82bbc1de5b6c963e6fe79e86f36580d" dependencies = [ "paste", "proc-macro2", @@ -10414,14 +10414,14 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.23.0" +version = "3.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" +checksum = "655da9c7eb6305c55742045d5a8d2037996d61d8de95806335c7c86ce0f82e9c" dependencies = [ "fastrand", "getrandom 0.3.4", "once_cell", - "rustix 1.1.2", + "rustix 1.1.3", "windows-sys 0.61.2", ] @@ -10476,7 +10476,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60b8cb979cb11c32ce1603f8137b22262a9d131aaa5c37b5678025f22b8becd0" dependencies = [ - "rustix 1.1.2", + "rustix 1.1.3", "windows-sys 0.60.2", ] @@ -11747,7 +11747,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3fabb953106c3c8eea8306e4393700d7657561cb43122571b172bbfb7c7ba1d" dependencies = [ "env_home", - "rustix 1.1.2", + "rustix 1.1.3", "winsafe", ] @@ -12411,9 +12411,15 @@ dependencies = [ [[package]] name = "zlib-rs" -version = "0.5.4" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40990edd51aae2c2b6907af74ffb635029d5788228222c4bb811e9351c0caad3" + +[[package]] +name = "zmij" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51f936044d677be1a1168fae1d03b583a285a5dd9d8cbf7b24c23aa1fc775235" +checksum = "e6d6085d62852e35540689d1f97ad663e3971fc19cf5eceab364d62c646ea167" [[package]] name = "zopfli" diff --git a/Cargo.toml b/Cargo.toml index dbeac987c0358..9f9fdc0498bdb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -268,8 +268,8 @@ alloy-transport = { version = "1.1.3", default-features = false } alloy-transport-http = { version = "1.1.3", default-features = false } alloy-transport-ipc = { version = "1.1.3", default-features = false } alloy-transport-ws = { version = "1.1.3", default-features = false } -alloy-hardforks = { version = "0.4.5", default-features = false } -alloy-op-hardforks = { version = "0.4.5", default-features = false } +alloy-hardforks = { version = "0.4.7", default-features = false } +alloy-op-hardforks = { version = "0.4.7", default-features = false } ## alloy-core alloy-dyn-abi = "1.5.1" diff --git a/crates/anvil/core/src/eth/mod.rs b/crates/anvil/core/src/eth/mod.rs index 34f44453998d7..43e0e8ecc7745 100644 --- a/crates/anvil/core/src/eth/mod.rs +++ b/crates/anvil/core/src/eth/mod.rs @@ -210,7 +210,7 @@ pub enum EthRequest { GetGenesisTime(()), #[serde(rename = "eth_getTransactionByBlockHashAndIndex")] - EthGetTransactionByBlockHashAndIndex(TxHash, Index), + EthGetTransactionByBlockHashAndIndex(B256, Index), #[serde(rename = "eth_getTransactionByBlockNumberAndIndex")] EthGetTransactionByBlockNumberAndIndex(BlockNumber, Index), @@ -219,7 +219,7 @@ pub enum EthRequest { EthGetRawTransactionByHash(TxHash), #[serde(rename = "eth_getRawTransactionByBlockHashAndIndex")] - EthGetRawTransactionByBlockHashAndIndex(TxHash, Index), + EthGetRawTransactionByBlockHashAndIndex(B256, Index), #[serde(rename = "eth_getRawTransactionByBlockNumberAndIndex")] EthGetRawTransactionByBlockNumberAndIndex(BlockNumber, Index), diff --git a/crates/anvil/src/eth/api.rs b/crates/anvil/src/eth/api.rs index 095d1337a3076..b8c193fca084e 100644 --- a/crates/anvil/src/eth/api.rs +++ b/crates/anvil/src/eth/api.rs @@ -29,7 +29,7 @@ use crate::{ filter::{EthFilter, Filters, LogsFilter}, mem::transaction_build, }; -use alloy_consensus::{Account, Blob, Transaction, TxEip4844Variant, transaction::Recovered}; +use alloy_consensus::{Blob, Transaction, TrieAccount, TxEip4844Variant, transaction::Recovered}; use alloy_dyn_abi::TypedData; use alloy_eips::{ eip2718::Encodable2718, @@ -751,7 +751,7 @@ impl EthApi { &self, address: Address, block_number: Option, - ) -> Result { + ) -> Result { node_info!("eth_getAccount"); let block_request = self.block_request(block_number).await?; diff --git a/crates/anvil/src/eth/backend/fork.rs b/crates/anvil/src/eth/backend/fork.rs index e251d8f11de81..995206fbfcc89 100644 --- a/crates/anvil/src/eth/backend/fork.rs +++ b/crates/anvil/src/eth/backend/fork.rs @@ -1,7 +1,7 @@ //! Support for forking off another client use crate::eth::{backend::db::Db, error::BlockchainError, pool::transactions::PoolTransaction}; -use alloy_consensus::Account; +use alloy_consensus::TrieAccount; use alloy_eips::eip2930::AccessListResult; use alloy_network::{AnyRpcBlock, AnyRpcTransaction, BlockResponse, TransactionResponse}; use alloy_primitives::{ @@ -297,7 +297,7 @@ impl ClientFork { &self, address: Address, blocknumber: u64, - ) -> Result { + ) -> Result { trace!(target: "backend::fork", "get_account={:?}", address); self.provider().get_account(address).block_id(blocknumber.into()).await } diff --git a/crates/anvil/src/eth/backend/mem/mod.rs b/crates/anvil/src/eth/backend/mem/mod.rs index 6cf5b085f4837..adc56fe33a711 100644 --- a/crates/anvil/src/eth/backend/mem/mod.rs +++ b/crates/anvil/src/eth/backend/mem/mod.rs @@ -33,8 +33,8 @@ use crate::{ }; use alloy_chains::NamedChain; use alloy_consensus::{ - Account, Blob, BlockHeader, EnvKzgSettings, Header, Signed, Transaction as TransactionTrait, - TxEnvelope, Typed2718, + Blob, BlockHeader, EnvKzgSettings, Header, Signed, Transaction as TransactionTrait, + TrieAccount, TxEnvelope, Typed2718, proofs::{calculate_receipt_root, calculate_transaction_root}, transaction::Recovered, }; @@ -1981,7 +1981,8 @@ impl Backend { GethDebugBuiltInTracerType::NoopTracer => Ok(NoopFrame::default().into()), GethDebugBuiltInTracerType::FourByteTracer | GethDebugBuiltInTracerType::MuxTracer - | GethDebugBuiltInTracerType::FlatCallTracer => { + | GethDebugBuiltInTracerType::FlatCallTracer + | GethDebugBuiltInTracerType::Erc7562Tracer => { Err(RpcError::invalid_params("unsupported tracer type").into()) } }, @@ -2569,7 +2570,7 @@ impl Backend { &self, address: Address, block_request: Option, - ) -> Result { + ) -> Result { self.with_database_at(block_request, |block_db, _| { let db = block_db.maybe_as_full_db().ok_or(BlockchainError::DataUnavailable)?; let account = db.get(&address).cloned().unwrap_or_default(); @@ -2577,7 +2578,7 @@ impl Backend { let code_hash = account.info.code_hash; let balance = account.info.balance; let nonce = account.info.nonce; - Ok(Account { balance, nonce, code_hash, storage_root }) + Ok(TrieAccount { balance, nonce, code_hash, storage_root }) }) .await? } @@ -2951,6 +2952,7 @@ impl Backend { } GethDebugBuiltInTracerType::NoopTracer | GethDebugBuiltInTracerType::MuxTracer + | GethDebugBuiltInTracerType::Erc7562Tracer | GethDebugBuiltInTracerType::FlatCallTracer => {} }, GethDebugTracerType::JsTracer(_code) => {} diff --git a/crates/anvil/src/tasks/mod.rs b/crates/anvil/src/tasks/mod.rs index deab3b29e38f3..2d73fc99d8364 100644 --- a/crates/anvil/src/tasks/mod.rs +++ b/crates/anvil/src/tasks/mod.rs @@ -63,7 +63,7 @@ impl TaskManager { /// let endpoint = "http://...."; /// let (api, handle) = spawn(NodeConfig::default().with_eth_rpc_url(Some(endpoint))).await; /// - /// let provider = RootProvider::connect_builtin(endpoint).await.unwrap(); + /// let provider = RootProvider::connect(endpoint).await.unwrap(); /// /// handle.task_manager().spawn_reset_on_new_polled_blocks(provider, api); /// # } @@ -120,7 +120,7 @@ impl TaskManager { /// # async fn t() { /// let (api, handle) = spawn(NodeConfig::default().with_eth_rpc_url(Some("http://...."))).await; /// - /// let provider = RootProvider::connect_builtin("ws://...").await.unwrap(); + /// let provider = RootProvider::connect("ws://...").await.unwrap(); /// /// handle.task_manager().spawn_reset_on_subscribed_blocks(provider, api); /// diff --git a/crates/anvil/tests/it/anvil_api.rs b/crates/anvil/tests/it/anvil_api.rs index fc89206db81fd..e675001d7a480 100644 --- a/crates/anvil/tests/it/anvil_api.rs +++ b/crates/anvil/tests/it/anvil_api.rs @@ -440,7 +440,7 @@ async fn can_get_node_info() { let block_number = provider.get_block_number().await.unwrap(); let block = provider.get_block(BlockId::from(block_number)).await.unwrap().unwrap(); - let hard_fork: &str = SpecId::PRAGUE.into(); + let hard_fork: &str = SpecId::OSAKA.into(); let expected_node_info = NodeInfo { current_block_number: 0_u64, diff --git a/crates/anvil/tests/it/api.rs b/crates/anvil/tests/it/api.rs index 979b40c86f0f8..41df263fec070 100644 --- a/crates/anvil/tests/it/api.rs +++ b/crates/anvil/tests/it/api.rs @@ -571,7 +571,7 @@ async fn test_fill_transaction_eip4844_blob_fee() { // EIP-4844 blob transaction with sidecar but no blob fee let mut tx_req = TransactionRequest::default().with_from(from).with_to(Address::random()); - tx_req.sidecar = Some(sidecar); + tx_req.sidecar = Some(sidecar.into()); tx_req.transaction_type = Some(3); // EIP-4844 let filled = api.fill_transaction(WithOtherFields::new(tx_req)).await.unwrap(); @@ -602,7 +602,7 @@ async fn test_fill_transaction_eip4844_preserves_blob_fee() { .with_from(from) .with_to(Address::random()) .with_max_fee_per_blob_gas(provided_blob_fee); - tx_req.sidecar = Some(sidecar); + tx_req.sidecar = Some(sidecar.into()); tx_req.transaction_type = Some(3); // EIP-4844 let filled = api.fill_transaction(WithOtherFields::new(tx_req)).await.unwrap(); diff --git a/crates/cheatcodes/assets/cheatcodes.json b/crates/cheatcodes/assets/cheatcodes.json index 8b6eeb049c9fd..2134b95ac571d 100644 --- a/crates/cheatcodes/assets/cheatcodes.json +++ b/crates/cheatcodes/assets/cheatcodes.json @@ -9994,9 +9994,9 @@ "func": { "id": "signCompact_0", "description": "Signs data with a `Wallet`.\nReturns a compact signature (`r`, `vs`) as per EIP-2098, where `vs` encodes both the\nsignature's `s` value, and the recovery id `v` in a single bytes32.\nThis format reduces the signature size from 65 to 64 bytes.", - "declaration": "function signCompact(Wallet calldata wallet, bytes32 digest) external returns (bytes32 r, bytes32 vs);", + "declaration": "function signCompact(Wallet calldata wallet, bytes32 digest) external pure returns (bytes32 r, bytes32 vs);", "visibility": "external", - "mutability": "", + "mutability": "pure", "signature": "signCompact((address,uint256,uint256,uint256),bytes32)", "selector": "0x3d0e292f", "selectorBytes": [ @@ -10174,9 +10174,9 @@ "func": { "id": "sign_0", "description": "Signs data with a `Wallet`.", - "declaration": "function sign(Wallet calldata wallet, bytes32 digest) external returns (uint8 v, bytes32 r, bytes32 s);", + "declaration": "function sign(Wallet calldata wallet, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s);", "visibility": "external", - "mutability": "", + "mutability": "pure", "signature": "sign((address,uint256,uint256,uint256),bytes32)", "selector": "0xb25c5a25", "selectorBytes": [ diff --git a/crates/cheatcodes/spec/src/vm.rs b/crates/cheatcodes/spec/src/vm.rs index 87d938db5691e..59b6d96eec2f1 100644 --- a/crates/cheatcodes/spec/src/vm.rs +++ b/crates/cheatcodes/spec/src/vm.rs @@ -2704,7 +2704,7 @@ interface Vm { /// Signs data with a `Wallet`. #[cheatcode(group = Crypto)] - function sign(Wallet calldata wallet, bytes32 digest) external returns (uint8 v, bytes32 r, bytes32 s); + function sign(Wallet calldata wallet, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s); /// Signs data with a `Wallet`. /// @@ -2712,7 +2712,7 @@ interface Vm { /// signature's `s` value, and the recovery id `v` in a single bytes32. /// This format reduces the signature size from 65 to 64 bytes. #[cheatcode(group = Crypto)] - function signCompact(Wallet calldata wallet, bytes32 digest) external returns (bytes32 r, bytes32 vs); + function signCompact(Wallet calldata wallet, bytes32 digest) external pure returns (bytes32 r, bytes32 vs); /// Signs `digest` with `privateKey` using the secp256k1 curve. #[cheatcode(group = Crypto)] diff --git a/crates/chisel/src/dispatcher.rs b/crates/chisel/src/dispatcher.rs index 6b611e795f3ce..a1497677aee18 100644 --- a/crates/chisel/src/dispatcher.rs +++ b/crates/chisel/src/dispatcher.rs @@ -132,8 +132,6 @@ impl ChiselDispatcher { // Create new source with exact input appended and parse let (new_source, do_execute) = source.clone_with_new_line(input.to_string())?; - // TODO: Cloning / parsing the session source twice on non-inspected inputs kinda sucks. - // Should change up how this works. let (cf, res) = source.inspect(input).await?; if let Some(res) = &res { let _ = sh_println!("{res}"); diff --git a/crates/chisel/src/executor.rs b/crates/chisel/src/executor.rs index f9cd04af13f6a..abb6be8693585 100644 --- a/crates/chisel/src/executor.rs +++ b/crates/chisel/src/executor.rs @@ -36,9 +36,7 @@ impl SessionSource { .ok_or_else(|| eyre::eyre!("No bytecode found for `REPL` contract"))?; Ok((bytecode.into_owned(), output.final_pc(contract)?)) })?; - - let Some(final_pc) = final_pc else { return Ok(Default::default()) }; - + let final_pc = final_pc.unwrap_or_default(); let mut runner = self.build_runner(final_pc).await?; runner.run(bytecode) } @@ -59,7 +57,7 @@ impl SessionSource { let mut source = match self.clone_with_new_line(line) { Ok((source, _)) => source, Err(err) => { - debug!(%err, "failed to build new source"); + debug!(%err, "failed to build new source for inspection"); return Ok((ControlFlow::Continue(()), None)); } }; diff --git a/crates/chisel/tests/it/repl/mod.rs b/crates/chisel/tests/it/repl/mod.rs index 9a24801752b4a..6fb38b6ca1805 100644 --- a/crates/chisel/tests/it/repl/mod.rs +++ b/crates/chisel/tests/it/repl/mod.rs @@ -19,14 +19,14 @@ macro_rules! repl_test { }; } -repl_test!(test_repl_help, |repl| { +repl_test!(repl_help, |repl| { repl.sendln_raw("!h"); repl.expect("Chisel help"); repl.expect_prompt(); }); // Test abi encode/decode. -repl_test!(test_abi_encode_decode, |repl| { +repl_test!(abi_encode_decode, |repl| { repl.sendln("bytes memory encoded = abi.encode(42, \"hello\")"); repl.sendln("(uint num, string memory str) = abi.decode(encoded, (uint, string))"); repl.sendln("num"); @@ -36,7 +36,7 @@ repl_test!(test_abi_encode_decode, |repl| { }); // Test 0x prefixed strings. -repl_test!(test_hex_string_interpretation, |repl| { +repl_test!(hex_string_interpretation, |repl| { repl.sendln("string memory s = \"0x1234\""); repl.sendln("s"); // Should be treated as string, not hex literal. @@ -44,7 +44,7 @@ repl_test!(test_hex_string_interpretation, |repl| { }); // Test cheatcodes availability. -repl_test!(test_cheatcodes_available, "", init = true, |repl| { +repl_test!(cheatcodes_available, "", init = true, |repl| { repl.sendln("address alice = address(0x1)"); repl.sendln("alice.balance"); @@ -60,12 +60,12 @@ repl_test!(test_cheatcodes_available, "", init = true, |repl| { }); // Test empty inputs. -repl_test!(test_empty_input, |repl| { +repl_test!(empty_input, |repl| { repl.sendln(" \n \n\n \t \t \n \n\t\t\t\t \n \n"); }); // Issue #4130: Test type(intN).min correctness. -repl_test!(test_int_min_values, |repl| { +repl_test!(int_min_values, |repl| { repl.sendln("type(int8).min"); repl.expect("-128"); repl.sendln("type(int256).min"); @@ -74,7 +74,7 @@ repl_test!(test_int_min_values, |repl| { // Issue #4393: Test edit command with traces. // TODO: test `!edit` -// repl_test!(test_edit_with_traces, |repl| { +// repl_test!(edit_with_traces, |repl| { // repl.sendln("!traces"); // repl.sendln("uint x = 42"); // repl.sendln("!edit"); @@ -83,7 +83,7 @@ repl_test!(test_int_min_values, |repl| { // }); // Test tuple support. -repl_test!(test_tuples, |repl| { +repl_test!(tuples, |repl| { repl.sendln("(uint a, uint b) = (1, 2)"); repl.sendln("a"); repl.expect("Decimal: 1"); @@ -92,7 +92,7 @@ repl_test!(test_tuples, |repl| { }); // Issue #4467: Test import. -repl_test!(test_import, "", init = true, |repl| { +repl_test!(import, "", init = true, |repl| { repl.sendln("import {Counter} from \"src/Counter.sol\""); repl.sendln("Counter c = new Counter()"); // TODO: pre-existing inspection failure. @@ -106,7 +106,7 @@ repl_test!(test_import, "", init = true, |repl| { }); // Issue #4617: Test code after assembly return. -repl_test!(test_assembly_return, |repl| { +repl_test!(assembly_return, |repl| { repl.sendln("uint x = 1;"); repl.sendln("assembly { mstore(0x0, 0x1337) return(0x0, 0x20) }"); repl.sendln("x = 2;"); @@ -116,25 +116,25 @@ repl_test!(test_assembly_return, |repl| { }); // Issue #4652: Test commands with trailing whitespace. -repl_test!(test_trailing_whitespace, |repl| { +repl_test!(trailing_whitespace, |repl| { repl.sendln("uint x = 42 "); repl.sendln("x"); repl.expect("Decimal: 42"); }); // Issue #4652: Test that solc flags are respected. -repl_test!(test_solc_flags, "--use 0.8.23", |repl| { +repl_test!(solc_flags, "--use 0.8.23", |repl| { repl.sendln("pragma solidity 0.8.24;"); repl.expect("invalid solc version"); }); // Issue #4915: `chisel eval` -repl_test!(test_eval_subcommand, "eval type(uint8).max", |repl| { +repl_test!(eval_subcommand, "eval type(uint8).max", |repl| { repl.expect("Decimal: 255"); }); // Issue #4938: Test memory/stack dumps with assembly. -repl_test!(test_assembly_memory_dump, |repl| { +repl_test!(assembly_memory_dump, |repl| { let input = r#" uint256 value = 12345; string memory str; @@ -154,34 +154,34 @@ assembly { }); // Issue #5051, #8978: Test EVM version normalization. -repl_test!(test_evm_version_normalization, "--use 0.7.6 --evm-version london", |repl| { +repl_test!(evm_version_normalization, "--use 0.7.6 --evm-version london", |repl| { repl.sendln("uint x;\nx"); repl.expect("Decimal: 0"); }); // Issue #5481: Test function return values are displayed. -repl_test!(test_function_return_display, |repl| { +repl_test!(function_return_display, |repl| { repl.sendln("function add(uint a, uint b) public pure returns (uint) { return a + b; }"); repl.sendln("add(2, 3)"); repl.expect("Decimal: 5"); }); // Issue #5737: Test bytesN return types. -repl_test!(test_bytes_length_type, |repl| { +repl_test!(bytes_length_type, |repl| { repl.sendln("bytes10 b = bytes10(0)"); repl.sendln("b.length"); repl.expect("Decimal: 10"); }); // Issue #5737: Test bytesN indexing return type. -repl_test!(test_bytes_index_type, |repl| { +repl_test!(bytes_index_type, |repl| { repl.sendln("bytes32 b = bytes32(uint256(0x0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20))"); repl.sendln("b[3]"); repl.expect("Data: 0x0400000000000000000000000000000000000000000000000000000000000000"); }); // Issue #6618: Test fetching interface with structs. -repl_test!(test_fetch_interface_with_structs, |repl| { +repl_test!(fetch_interface_with_structs, |repl| { repl.sendln_raw("!fe 0x5ff137d4b0fdcd49dca30c7cf57e578a026d2789 IEntryPoint"); repl.expect( "Added 0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789's interface to source as `IEntryPoint`", @@ -192,7 +192,7 @@ repl_test!(test_fetch_interface_with_structs, |repl| { }); // Issue #7035: Test that hex strings aren't checksummed as addresses. -repl_test!(test_hex_string_no_checksum, |repl| { +repl_test!(hex_string_no_checksum, |repl| { repl.sendln("function test(string memory s) public pure returns (string memory) { return s; }"); repl.sendln("test(\"0xe5f3af50fe5d0bf402a3c6f55ccc47d4307922d4\")"); // Should return the exact string, not checksummed. @@ -200,7 +200,7 @@ repl_test!(test_hex_string_no_checksum, |repl| { }); // Issue #7050: Test enum min/max operations. -repl_test!(test_enum_min_max, |repl| { +repl_test!(enum_min_max, |repl| { repl.sendln("enum Color { Red, Green, Blue }"); repl.sendln("type(Color).min"); repl.expect("Decimal: 0"); @@ -209,7 +209,7 @@ repl_test!(test_enum_min_max, |repl| { }); // Issue #9377: Test correct hex formatting for uint256. -repl_test!(test_uint256_hex_formatting, |repl| { +repl_test!(uint256_hex_formatting, |repl| { repl.sendln("uint256 x = 42"); // Full word hex should be 64 chars (256 bits). repl.sendln("x"); @@ -217,7 +217,7 @@ repl_test!(test_uint256_hex_formatting, |repl| { }); // Issue #9377: Test that full words are printed correctly. -repl_test!(test_full_word_hex_formatting, |repl| { +repl_test!(full_word_hex_formatting, |repl| { repl.sendln(r#"keccak256(abi.encode(uint256(keccak256("AgoraStableSwapStorage.OracleStorage")) - 1)) & ~bytes32(uint256(0xff))"#); repl.expect( "Hex (full word): 0x0a6b316b47a0cd26c1b582ae3dcffbd175283c221c3cb3d1c614e3e47f62a700", @@ -225,7 +225,7 @@ repl_test!(test_full_word_hex_formatting, |repl| { }); // Test that uint is printed properly with any size. -repl_test!(test_uint_formatting, |repl| { +repl_test!(uint_formatting, |repl| { for size in (8..=256).step_by(8) { repl.sendln(&format!("type(uint{size}).max")); repl.expect(&format!("Hex: 0x{}", "f".repeat(size / 4))); @@ -236,7 +236,7 @@ repl_test!(test_uint_formatting, |repl| { }); // Test that int is printed properly with any size. -repl_test!(test_int_formatting, |repl| { +repl_test!(int_formatting, |repl| { for size in (8..=256).step_by(8) { let size_minus_1: usize = size / 4 - 1; repl.sendln(&format!("type(int{size}).max")); @@ -252,3 +252,15 @@ repl_test!(test_int_formatting, |repl| { repl.expect(&format!("Hex: 0x{}e", "f".repeat(size_minus_1))); } }); + +repl_test!(uninitialized_variables, |repl| { + repl.sendln("uint256 x;"); + repl.sendln("address y;"); + repl.sendln("assembly { y := not(x) }"); + + repl.sendln("x"); + repl.expect("Hex: 0x0"); + + repl.sendln("y"); + repl.expect("Data: 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF"); +}); diff --git a/crates/config/src/compilation.rs b/crates/config/src/compilation.rs index bdd222348d055..492a18a0a96d6 100644 --- a/crates/config/src/compilation.rs +++ b/crates/config/src/compilation.rs @@ -7,7 +7,7 @@ use foundry_compilers::{ solc::{Restriction, SolcRestrictions}, }; use semver::VersionReq; -use serde::{Deserialize, Serialize}; +use serde::{Deserialize, Deserializer, Serialize}; /// Keeps possible overrides for default settings which users may configure to construct additional /// settings profile. @@ -69,6 +69,7 @@ pub enum RestrictionsError { #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct CompilationRestrictions { pub paths: GlobMatcher, + #[serde(default, deserialize_with = "deserialize_version_req")] pub version: Option, pub via_ir: Option, pub bytecode_hash: Option, @@ -85,6 +86,36 @@ pub struct CompilationRestrictions { pub max_evm_version: Option, } +/// Custom deserializer for version field that rejects ambiguous bare version numbers. +fn deserialize_version_req<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + let opt_string: Option = Option::deserialize(deserializer)?; + let Some(opt_string) = opt_string else { + return Ok(None); + }; + + let version = opt_string.trim(); + // Reject bare versions like "0.8.11" that lack an operator prefix + if version.chars().next().is_some_and(|c| c.is_ascii_digit()) { + return Err(serde::de::Error::custom(format!( + "Invalid version format '{opt_string}' in compilation_restrictions. \ + Bare version numbers are ambiguous because Cargo interprets them as caret requirements (e.g. '^{version}'). \ + Use an explicit constraint such as '={version}' for an exact version or '>={version}' for a minimum version." + ))); + } + + let req = VersionReq::parse(&opt_string).map_err(|e| { + serde::de::Error::custom(format!( + "Invalid version requirement '{opt_string}': {e}. \ + Examples: '=0.8.11' (exact), '>=0.8.11' (minimum), '>=0.8.11 <0.9.0' (range)." + )) + })?; + + Ok(Some(req)) +} + impl TryFrom for RestrictionsWithVersion { type Error = RestrictionsError; diff --git a/crates/config/src/lib.rs b/crates/config/src/lib.rs index 17f13a3921fe5..d54cb0aac63f5 100644 --- a/crates/config/src/lib.rs +++ b/crates/config/src/lib.rs @@ -6413,4 +6413,57 @@ mod tests { Ok(()) }); } + + #[test] + fn fails_on_ambiguous_version_in_compilation_restrictions() { + figment::Jail::expect_with(|jail| { + jail.create_file( + "foundry.toml", + r#" + [profile.default] + src = "src" + + [[profile.default.compilation_restrictions]] + paths = "src/*.sol" + version = "0.8.11" + "#, + )?; + + let err = Config::load().expect_err("expected bare version to fail"); + let err_msg = err.to_string(); + assert!( + err_msg.contains("Invalid version format '0.8.11'") + && err_msg.contains("Bare version numbers are ambiguous"), + "Expected error about ambiguous version, got: {err_msg}" + ); + + Ok(()) + }); + } + + #[test] + fn accepts_explicit_version_requirements() { + figment::Jail::expect_with(|jail| { + jail.create_file( + "foundry.toml", + r#" + [profile.default] + src = "src" + + [[profile.default.compilation_restrictions]] + paths = "src/*.sol" + version = "=0.8.11" + + [[profile.default.compilation_restrictions]] + paths = "test/*.sol" + version = ">=0.8.11" + "#, + )?; + + let config = Config::load().expect("should accept explicit version requirements"); + assert_eq!(config.compilation_restrictions.len(), 2); + + Ok(()) + }); + } } diff --git a/crates/evm/core/src/backend/mod.rs b/crates/evm/core/src/backend/mod.rs index 26e56e7bf883f..6429ceb3db23f 100644 --- a/crates/evm/core/src/backend/mod.rs +++ b/crates/evm/core/src/backend/mod.rs @@ -6,7 +6,7 @@ use crate::{ evm::new_evm_with_inspector, fork::{CreateFork, ForkId, MultiFork}, state_snapshot::StateSnapshots, - utils::{configure_tx_env, configure_tx_req_env, get_blob_base_fee_update_fraction_by_spec_id}, + utils::{configure_tx_env, configure_tx_req_env, get_blob_base_fee_update_fraction}, }; use alloy_consensus::Typed2718; use alloy_evm::Evm; @@ -1954,7 +1954,7 @@ fn update_env_block(env: &mut EnvMut<'_>, block: &AnyRpcBlock) { if let Some(excess_blob_gas) = block.header.excess_blob_gas { env.block.blob_excess_gas_and_price = Some(BlobExcessGasAndPrice::new( excess_blob_gas, - get_blob_base_fee_update_fraction_by_spec_id(env.cfg.spec), + get_blob_base_fee_update_fraction(env.cfg.chain_id, block.header.timestamp), )); } } diff --git a/crates/forge/tests/cli/test_cmd/mod.rs b/crates/forge/tests/cli/test_cmd/mod.rs index 9666cf4d7e69d..0abffff57c4a8 100644 --- a/crates/forge/tests/cli/test_cmd/mod.rs +++ b/crates/forge/tests/cli/test_cmd/mod.rs @@ -678,6 +678,33 @@ Ran 1 test suite [ELAPSED]: 1 tests passed, 0 failed, 0 skipped (1 total tests) "#]]); }); +// Validates BPO1 blob gas price calculation during fork transaction replay. +// Block 24127158 has a blob tx at index 0, target tx at index 1. +// Forking at the target tx replays the blob tx with correct BPO1 blob base fee calculation. +forgetest_init!(fork_tx_replay_bpo1_blob_base_fee, |prj, cmd| { + let endpoint = rpc::next_http_archive_rpc_url(); + + prj.add_test( + "BlobFork.t.sol", + &r#" +import {Test} from "forge-std/Test.sol"; + +contract BlobForkTest is Test { + function test_fork_with_blob_replay() public { + // Fork at tx index 1 in block 24127158, which replays blob tx at index 0 + bytes32 txHash = 0xa0f349b16e0f338ee760a9954ff5dbf2a402cff3320f3fe2c3755aee8babc335; + vm.createSelectFork("", txHash); + // If we get here, blob tx replay succeeded + assertTrue(true); + } +} + "# + .replace("", &endpoint), + ); + + cmd.args(["test", "-vvvv"]).assert_success(); +}); + // https://github.com/foundry-rs/foundry/issues/6579 forgetest_init!(include_custom_types_in_traces, |prj, cmd| { prj.add_test( diff --git a/crates/linking/src/lib.rs b/crates/linking/src/lib.rs index 0066ab7c83843..ebf33383c9491 100644 --- a/crates/linking/src/lib.rs +++ b/crates/linking/src/lib.rs @@ -697,6 +697,7 @@ mod tests { } #[test] + #[ignore = "addresses depend on testdata utils internals for some reason"] fn link_create2_nested() { link_test(testdata().join("default/linking/nested"), |linker| { linker diff --git a/crates/test-utils/src/rpc.rs b/crates/test-utils/src/rpc.rs index 336ea499fff41..cccde297ef967 100644 --- a/crates/test-utils/src/rpc.rs +++ b/crates/test-utils/src/rpc.rs @@ -187,6 +187,13 @@ fn next_url_inner(is_ws: bool, chain: NamedChain) -> String { return "https://celo.drpc.org".to_string(); } + if matches!(chain, Sepolia) { + let rpc_url = env::var("ETH_SEPOLIA_RPC").unwrap_or_default(); + if !rpc_url.is_empty() { + return rpc_url; + } + } + if matches!(chain, Arbitrum) { let rpc_url = env::var("ARBITRUM_RPC").unwrap_or_default(); if !rpc_url.is_empty() { diff --git a/deny.toml b/deny.toml index dfe4f0128f313..854f33033ed2c 100644 --- a/deny.toml +++ b/deny.toml @@ -9,6 +9,8 @@ ignore = [ "RUSTSEC-2024-0436", # https://rustsec.org/advisories/RUSTSEC-2024-0437 protobuf! Crash due to uncontrolled recursion in protobuf crate. "RUSTSEC-2024-0437", + # https://rustsec.org/advisories/RUSTSEC-2025-0137 `reciprocal_mg10` OOB, unused + "RUSTSEC-2025-0137", ] # This section is considered when running `cargo deny check bans`. diff --git a/flake.lock b/flake.lock index bd08c4fc369a7..48f8b3851e80f 100644 --- a/flake.lock +++ b/flake.lock @@ -8,11 +8,11 @@ "rust-analyzer-src": "rust-analyzer-src" }, "locked": { - "lastModified": 1766267710, - "narHash": "sha256-2icDwxnuPUl+vA5YwxbiFdRGlO/IrBH5Jllu8aswCkc=", + "lastModified": 1766818130, + "narHash": "sha256-FeVBDk9H5OPynbG+4wx0j04Mz/F+/LUfAPr4bnSeu/8=", "owner": "nix-community", "repo": "fenix", - "rev": "16642c5ae9941c36e4e3acb4ea02fd4959012010", + "rev": "3479aaf375090ede15fb623a84892f8597e00a25", "type": "github" }, "original": { @@ -23,11 +23,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1766125104, - "narHash": "sha256-l/YGrEpLromL4viUo5GmFH3K5M1j0Mb9O+LiaeCPWEM=", + "lastModified": 1766840161, + "narHash": "sha256-Ss/LHpJJsng8vz1Pe33RSGIWUOcqM1fjrehjUkdrWio=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "7d853e518814cca2a657b72eeba67ae20ebf7059", + "rev": "3edc4a30ed3903fdf6f90c837f961fa6b49582d1", "type": "github" }, "original": { @@ -46,11 +46,11 @@ "rust-analyzer-src": { "flake": false, "locked": { - "lastModified": 1766021917, - "narHash": "sha256-UfHpZWcVQouCRf64yAJGletSAuiAOmHnlmhHrsKTQtk=", + "lastModified": 1766755908, + "narHash": "sha256-1SBtDgvqG/tazoe3nyIfqhFgEI6RFSGBnh1Lnv0/Y6U=", "owner": "rust-lang", "repo": "rust-analyzer", - "rev": "ea1d2998f2b3c6f6a494f72580550d521548e3d9", + "rev": "8c5a68e214578d4ccbb65fa8c48a4efd5c82697f", "type": "github" }, "original": { diff --git a/testdata/default/repros/Issue2851.t.sol b/testdata/default/repros/Issue2851.t.sol deleted file mode 100644 index bafa7c0ed0d07..0000000000000 --- a/testdata/default/repros/Issue2851.t.sol +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.1; - -import "utils/Test.sol"; - -contract Backdoor { - uint256 public number = 1; - - function backdoor(uint256 newNumber) public payable { - uint256 x = newNumber - 1; - if (x == 6912213124124531) { - number = 0; - } - } -} - -// https://github.com/foundry-rs/foundry/issues/2851 -contract Issue2851Test is Test { - Backdoor back; - - function setUp() public { - back = new Backdoor(); - } - - /// forge-config: default.fuzz.dictionary.max_fuzz_dictionary_literals = 0 - /// forge-config: default.fuzz.seed = '111' - function invariantNotZero() public { - assertEq(back.number(), 1); - } -} diff --git a/testdata/utils/Vm.sol b/testdata/utils/Vm.sol index cf5930928cf8e..8cced251493aa 100644 --- a/testdata/utils/Vm.sol +++ b/testdata/utils/Vm.sol @@ -492,7 +492,7 @@ interface Vm { function signAndAttachDelegation(address implementation, uint256 privateKey) external returns (SignedDelegation memory signedDelegation); function signAndAttachDelegation(address implementation, uint256 privateKey, uint64 nonce) external returns (SignedDelegation memory signedDelegation); function signAndAttachDelegation(address implementation, uint256 privateKey, bool crossChain) external returns (SignedDelegation memory signedDelegation); - function signCompact(Wallet calldata wallet, bytes32 digest) external returns (bytes32 r, bytes32 vs); + function signCompact(Wallet calldata wallet, bytes32 digest) external pure 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); @@ -501,7 +501,7 @@ interface Vm { function signDelegation(address implementation, uint256 privateKey, bool crossChain) external returns (SignedDelegation memory signedDelegation); function signP256(uint256 privateKey, bytes32 digest) external pure returns (bytes32 r, bytes32 s); function signWithNonceUnsafe(uint256 privateKey, bytes32 digest, uint256 nonce) external pure returns (uint8 v, bytes32 r, bytes32 s); - function sign(Wallet calldata wallet, bytes32 digest) external returns (uint8 v, bytes32 r, bytes32 s); + function sign(Wallet calldata wallet, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s); function sign(uint256 privateKey, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s); function sign(bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s); function sign(address signer, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s); From 818f43b6a4f5e94ba5e9d6b1af4d03699a883065 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Wed, 31 Dec 2025 21:58:07 +0700 Subject: [PATCH 171/232] Create ci-web3-gamefi.yml (#217) (#289) Introduce a basic CircleCI pipeline for the web3 GameFi project, providing a custom Docker executor and a stub job within a workflow. CI: Add CircleCI config file ci-web3-gamefi.yml with version 2.1 pipeline Define a custom executor using the cimg/base:stable Docker image with Docker Hub credentials Create a web3-defi-game-project- job and integrate it into a my-custom-workflow Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> From 3478be83972d1822a47bec3a0980894acc71e534 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Wed, 31 Dec 2025 22:13:06 +0700 Subject: [PATCH 172/232] Merge pull request #47 (#290) * Add .circleci/config.yml * Updated config.yml * Updated config.yml * Updated config.yml * Update test.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 19: Workflow does not contain permissions Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Update test.yml (#46) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * chore(deps): bump revm to 24.0.0 (#10601) * feat: implement add_balance endpoint (#10636) * fix(bindings): ensure forge bind generates snake_case file names (#10622) * fix(bindings): ensure forge bind generates snake_case file names * refactor: use heck crate for snake_case conversion --------- Co-authored-by: zerosnacks <95942363+zerosnacks@users.noreply.github.com> * chore: standardize lint help + validate docs existance (#10639) * feat(cast mktx): add support for "--ethsign" option (#10641) - Sign transactions using "eth_signTransaction" on local node with unlocked accounts. - Same TX building logic as in "cast send --unlocked". - Added a test case to validate the new functionality. * chore(wallets): improve error message for signer instantiation failure (#10646) chore(wallets): improve error message on signer instantiation failure * chore: replaced anvil hardforks with alloy hardforks (#10612) * chore: replaced anvil hardforks with alloy hardforks * fixes * fixes * fixes * removed redundant op and alloy hardforks enum * fixes * fixes * bumped alloy hardforks and kept default to prague and isthmus * bumped alloy-hardforks and fixes --------- Co-authored-by: zerosnacks <95942363+zerosnacks@users.noreply.github.com> * fix(`anvil`): latest evm version should be prague (#10653) * fix(`anvil`): latest evm version should be prague * fix test * nit * chore(deps): bump tracing-subscriber (#51) Bumps the cargo group with 1 update in the / directory: [tracing-subscriber](https://github.com/tokio-rs/tracing). Updates `tracing-subscriber` from 0.3.19 to 0.3.20 - [Release notes](https://github.com/tokio-rs/tracing/releases) - [Commits](https://github.com/tokio-rs/tracing/compare/tracing-subscriber-0.3.19...tracing-subscriber-0.3.20) --- updated-dependencies: - dependency-name: tracing-subscriber dependency-version: 0.3.20 dependency-type: direct:production dependency-group: cargo ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Update test.yml (#52) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Update docker-image.yml (#53) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Create ci_cargo.yml (#59) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Create web3_defi_gamefi.yml (#61) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Update dependencies.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 21: Workflow does not contain permissions Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Update dependencies.yml Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update dependencies.yml (#247) Improve readability of the GitHub Actions dependencies workflow by adjusting whitespace and adding blank lines CI: Add blank line before the workflow name declaration Insert blank line after the scheduled cron job entry Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update dependencies.yml (#248) CI: Remove extraneous blank line in .github/workflows/dependencies.yml Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update test.yml (#249) CI: Remove dev branch from test workflow triggers Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --------- Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Signed-off-by: dependabot[bot] Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Co-authored-by: zerosnacks <95942363+zerosnacks@users.noreply.github.com> Co-authored-by: pistomat Co-authored-by: zark <77061323+zarkk01@users.noreply.github.com> Co-authored-by: 0xrusowsky <90208954+0xrusowsky@users.noreply.github.com> Co-authored-by: Mablr <59505383+mablr@users.noreply.github.com> Co-authored-by: Ishika Choudhury <117741714+Rimeeeeee@users.noreply.github.com> Co-authored-by: Yash Atreya <44857776+yash-atreya@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .circleci/ci_cargo.yml | 37 +++++ .circleci/web3_defi_gamefi.yml | 26 ++++ crates/cast/src/cmd/mktx.rs | 26 +--- crates/forge/Cargo.toml | 1 + crates/lint/src/linter.rs | 129 ++++++++++++++++++ crates/lint/src/sol/gas/keccak.rs | 98 ++----------- .../lint/testdata/DivideBeforeMultiply.stderr | 64 ++++----- 7 files changed, 243 insertions(+), 138 deletions(-) create mode 100644 .circleci/ci_cargo.yml create mode 100644 .circleci/web3_defi_gamefi.yml create mode 100644 crates/lint/src/linter.rs diff --git a/.circleci/ci_cargo.yml b/.circleci/ci_cargo.yml new file mode 100644 index 0000000000000..46a18d45a5fca --- /dev/null +++ b/.circleci/ci_cargo.yml @@ -0,0 +1,37 @@ +version: 2.1 + +jobs: + build-and-test: + docker: + - image: cimg/rust:1.88.0 + steps: + - checkout + - restore_cache: + keys: + - v1-cargo-{{ checksum "Cargo.lock" }} + - v1-cargo- + - run: + name: "Check formatting" + command: cargo fmt -- --check + - run: + name: "Run tests" + command: cargo test + - save_cache: + key: v1-cargo-{{ checksum "Cargo.lock" }} + paths: + - "~/.cargo/bin" + - "~/.cargo/registry/index" + - "~/.cargo/registry/cache" + - "~/.cargo/git/db" + - "target" + - run: + name: "Check formatting" + command: cargo fmt -- --check + - run: + name: "Run tests" + command: cargo test + +workflows: + ci: + jobs: + - build-and-test diff --git a/.circleci/web3_defi_gamefi.yml b/.circleci/web3_defi_gamefi.yml new file mode 100644 index 0000000000000..edb6605e3f101 --- /dev/null +++ b/.circleci/web3_defi_gamefi.yml @@ -0,0 +1,26 @@ +# Use the latest 2.1 version of CircleCI pipeline process engine. +# See: https://circleci.com/docs/configuration-reference + +version: 2.1 +executors: + my-custom-executor: + docker: + - image: cimg/base:stable + auth: + # ensure you have first added these secrets + # visit app.circleci.com/settings/project/github/Dargon789/foundry/environment-variables + username: $DOCKER_HUB_USER + password: $DOCKER_HUB_PASSWORD +jobs: + web3-defi-game-project-: + + executor: my-custom-executor + steps: + - checkout + - run: | + # echo Hello, World! + +workflows: + my-custom-workflow: + jobs: + - web3-defi-game-project- diff --git a/crates/cast/src/cmd/mktx.rs b/crates/cast/src/cmd/mktx.rs index b4a9c0fb681bd..ebfb5afeadd47 100644 --- a/crates/cast/src/cmd/mktx.rs +++ b/crates/cast/src/cmd/mktx.rs @@ -1,14 +1,14 @@ use crate::tx::{self, CastTxBuilder}; use alloy_ens::NameOrAddress; -use alloy_network::{EthereumWallet, TransactionBuilder, eip2718::Encodable2718}; -use alloy_primitives::{Address, hex}; +use alloy_network::{eip2718::Encodable2718, EthereumWallet, TransactionBuilder}; +use alloy_primitives::hex; use alloy_provider::Provider; use alloy_signer::Signer; use clap::Parser; -use eyre::Result; +use eyre::{OptionExt, Result}; use foundry_cli::{ opts::{EthereumOpts, TransactionOpts}, - utils::{LoadConfig, get_provider}, + utils::{get_provider, LoadConfig}, }; use std::{path::PathBuf, str::FromStr}; @@ -25,7 +25,6 @@ pub struct MakeTxArgs { sig: Option, /// The arguments of the function to call. - #[arg(allow_negative_numbers = true)] args: Vec, #[command(subcommand)] @@ -50,7 +49,7 @@ pub struct MakeTxArgs { /// Generate a raw RLP-encoded unsigned transaction. /// /// Relaxes the wallet requirement. - #[arg(long)] + #[arg(long, requires = "from")] raw_unsigned: bool, /// Call `eth_signTransaction` using the `--from` argument or $ETH_FROM as sender @@ -70,7 +69,6 @@ pub enum MakeTxSubcommands { sig: Option, /// The constructor arguments. - #[arg(allow_negative_numbers = true)] args: Vec, }, } @@ -98,7 +96,7 @@ impl MakeTxArgs { let provider = get_provider(&config)?; - let tx_builder = CastTxBuilder::new(&provider, tx.clone(), &config) + let tx_builder = CastTxBuilder::new(&provider, tx, &config) .await? .with_to(to) .await? @@ -108,17 +106,7 @@ impl MakeTxArgs { if raw_unsigned { // Build unsigned raw tx - // Check if nonce is provided when --from is not specified - // See: - if eth.wallet.from.is_none() && tx.nonce.is_none() { - eyre::bail!( - "Missing required parameters for raw unsigned transaction. When --from is not provided, you must specify: --nonce" - ); - } - - // Use zero address as placeholder for unsigned transactions - let from = eth.wallet.from.unwrap_or(Address::ZERO); - + let from = eth.wallet.from.ok_or_eyre("missing `--from` address")?; let raw_tx = tx_builder.build_unsigned_raw(from).await?; sh_println!("{raw_tx}")?; diff --git a/crates/forge/Cargo.toml b/crates/forge/Cargo.toml index 53b5243d54b38..515983876019c 100644 --- a/crates/forge/Cargo.toml +++ b/crates/forge/Cargo.toml @@ -62,6 +62,7 @@ alloy-rpc-types.workspace = true alloy-serde.workspace = true alloy-signer.workspace = true alloy-transport.workspace = true +alloy-hardforks.workspace = true revm.workspace = true diff --git a/crates/lint/src/linter.rs b/crates/lint/src/linter.rs new file mode 100644 index 0000000000000..2c11e0222a286 --- /dev/null +++ b/crates/lint/src/linter.rs @@ -0,0 +1,129 @@ +use foundry_compilers::Language; +use foundry_config::lint::Severity; +use solar_ast::{visit::Visit, Expr, ItemFunction, ItemStruct, VariableDefinition}; +use solar_interface::{ + data_structures::Never, + diagnostics::{DiagBuilder, DiagId, MultiSpan}, + Session, Span, +}; +use std::{ops::ControlFlow, path::PathBuf}; + +/// Trait representing a generic linter for analyzing and reporting issues in smart contract source +/// code files. A linter can be implemented for any smart contract language supported by Foundry. +/// +/// # Type Parameters +/// +/// - `Language`: Represents the target programming language. Must implement the [`Language`] trait. +/// - `Lint`: Represents the types of lints performed by the linter. Must implement the [`Lint`] +/// trait. +/// +/// # Required Methods +/// +/// - `lint`: Scans the provided source files emitting a daignostic for lints found. +pub trait Linter: Send + Sync + Clone { + type Language: Language; + type Lint: Lint; + + fn lint(&self, input: &[PathBuf]); +} + +pub trait Lint { + fn id(&self) -> &'static str; + fn severity(&self) -> Severity; + fn description(&self) -> &'static str; + fn help(&self) -> &'static str; +} + +pub struct LintContext<'s> { + sess: &'s Session, + desc: bool, +} + +impl<'s> LintContext<'s> { + pub fn new(sess: &'s Session, with_description: bool) -> Self { + Self { sess, desc: with_description } + } + + // Helper method to emit diagnostics easily from passes + pub fn emit(&self, lint: &'static L, span: Span) { + let desc = if self.desc { lint.description() } else { "" }; + let diag: DiagBuilder<'_, ()> = self + .sess + .dcx + .diag(lint.severity().into(), desc) + .code(DiagId::new_str(lint.id())) + .span(MultiSpan::from_span(span)) + .help(lint.help()); + + diag.emit(); + } +} + +/// Trait for lints that operate directly on the AST. +/// Its methods mirror `solar_ast::visit::Visit`, with the addition of `LintCotext`. +pub trait EarlyLintPass<'ast>: Send + Sync { + fn check_expr(&mut self, _ctx: &LintContext<'_>, _expr: &'ast Expr<'ast>) {} + fn check_item_struct(&mut self, _ctx: &LintContext<'_>, _struct: &'ast ItemStruct<'ast>) {} + fn check_item_function(&mut self, _ctx: &LintContext<'_>, _func: &'ast ItemFunction<'ast>) {} + fn check_variable_definition( + &mut self, + _ctx: &LintContext<'_>, + _var: &'ast VariableDefinition<'ast>, + ) { + } + + // TODO: Add methods for each required AST node type +} + +/// Visitor struct for `EarlyLintPass`es +pub struct EarlyLintVisitor<'a, 's, 'ast> { + pub ctx: &'a LintContext<'s>, + pub passes: &'a mut [Box + 's>], +} + +impl<'s, 'ast> Visit<'ast> for EarlyLintVisitor<'_, 's, 'ast> +where + 's: 'ast, +{ + type BreakValue = Never; + + fn visit_expr(&mut self, expr: &'ast Expr<'ast>) -> ControlFlow { + for pass in self.passes.iter_mut() { + pass.check_expr(self.ctx, expr) + } + self.walk_expr(expr) + } + + fn visit_variable_definition( + &mut self, + var: &'ast VariableDefinition<'ast>, + ) -> ControlFlow { + for pass in self.passes.iter_mut() { + pass.check_variable_definition(self.ctx, var) + } + self.walk_variable_definition(var) + } + + fn visit_item_struct( + &mut self, + strukt: &'ast ItemStruct<'ast>, + ) -> ControlFlow { + for pass in self.passes.iter_mut() { + pass.check_item_struct(self.ctx, strukt) + } + self.walk_item_struct(strukt) + } + + fn visit_item_function( + &mut self, + func: &'ast ItemFunction<'ast>, + ) -> ControlFlow { + for pass in self.passes.iter_mut() { + pass.check_item_function(self.ctx, func) + } + self.walk_item_function(func) + } + + // TODO: Add methods for each required AST node type, mirroring `solar_ast::visit::Visit` method + // sigs + adding `LintContext` +} diff --git a/crates/lint/src/sol/gas/keccak.rs b/crates/lint/src/sol/gas/keccak.rs index cb942510bbb49..7316f4c4239b7 100644 --- a/crates/lint/src/sol/gas/keccak.rs +++ b/crates/lint/src/sol/gas/keccak.rs @@ -1,103 +1,27 @@ use super::AsmKeccak256; use crate::{ - linter::{LateLintPass, LintContext}, + declare_forge_lint, + linter::EarlyLintPass, sol::{Severity, SolLint}, }; -use solar::{ - ast::{self as ast, Span}, - interface::kw, - sema::hir::{self}, -}; +use solar_ast::{Expr, ExprKind}; +use solar_interface::kw; declare_forge_lint!( ASM_KECCAK256, Severity::Gas, "asm-keccak256", - "use of inefficient hashing mechanism; consider using inline assembly" + "hash using inline assembly to save gas" ); -impl<'hir> LateLintPass<'hir> for AsmKeccak256 { - fn check_stmt( - &mut self, - ctx: &LintContext, - hir: &'hir hir::Hir<'hir>, - stmt: &'hir hir::Stmt<'hir>, - ) { - let check_expr_and_emit_lint = - |expr: &'hir hir::Expr<'hir>, assign: Option, is_return: bool| { - if let Some(hash_arg) = extract_keccak256_arg(expr) { - self.emit_lint( - ctx, - hir, - stmt.span, - expr, - hash_arg, - AsmContext { _assign: assign, _is_return: is_return }, - ); - } - }; - - match stmt.kind { - hir::StmtKind::DeclSingle(var_id) => { - let var = hir.variable(var_id); - if let Some(init) = var.initializer { - // Constants should be optimized by the compiler, so no gas savings apply. - if !matches!(var.mutability, Some(hir::VarMut::Constant)) { - check_expr_and_emit_lint(init, var.name, false); - } +impl<'ast> EarlyLintPass<'ast> for AsmKeccak256 { + fn check_expr(&mut self, ctx: &crate::linter::LintContext<'_>, expr: &'ast Expr<'ast>) { + if let ExprKind::Call(expr, _) = &expr.kind { + if let ExprKind::Ident(ident) = &expr.kind { + if ident.name == kw::Keccak256 { + ctx.emit(&ASM_KECCAK256, expr.span); } } - // Expressions that don't (directly) assign to a variable - hir::StmtKind::Expr(expr) - | hir::StmtKind::Emit(expr) - | hir::StmtKind::Revert(expr) - | hir::StmtKind::DeclMulti(_, expr) - | hir::StmtKind::If(expr, ..) => check_expr_and_emit_lint(expr, None, false), - hir::StmtKind::Return(Some(expr)) => check_expr_and_emit_lint(expr, None, true), - _ => (), } } } - -impl AsmKeccak256 { - /// Emits lints (when possible with fix suggestions) for inefficient `keccak256` calls. - fn emit_lint( - &self, - ctx: &LintContext, - _hir: &hir::Hir<'_>, - _stmt_span: Span, - call: &hir::Expr<'_>, - _hash: &hir::Expr<'_>, - _asm_ctx: AsmContext, - ) { - ctx.emit(&ASM_KECCAK256, call.span); - } -} - -/// If the expression is a call to `keccak256` with one argument, returns that argument. -fn extract_keccak256_arg<'hir>(expr: &'hir hir::Expr<'hir>) -> Option<&'hir hir::Expr<'hir>> { - let hir::ExprKind::Call( - callee, - hir::CallArgs { kind: hir::CallArgsKind::Unnamed(args), .. }, - .., - ) = &expr.kind - else { - return None; - }; - - let is_keccak = if let hir::ExprKind::Ident([hir::Res::Builtin(builtin)]) = callee.kind { - matches!(builtin.name(), kw::Keccak256) - } else { - return None; - }; - - if is_keccak && args.len() == 1 { Some(&args[0]) } else { None } -} - -// -- HELPER FUNCTIONS AND STRUCTS ---------------------------------------------------------------- - -#[derive(Debug, Clone, Copy)] -struct AsmContext { - _assign: Option, - _is_return: bool, -} diff --git a/crates/lint/testdata/DivideBeforeMultiply.stderr b/crates/lint/testdata/DivideBeforeMultiply.stderr index 7677d97452527..1c98f4b13d194 100644 --- a/crates/lint/testdata/DivideBeforeMultiply.stderr +++ b/crates/lint/testdata/DivideBeforeMultiply.stderr @@ -1,48 +1,48 @@ warning[divide-before-multiply]: multiplication should occur before division to avoid loss of precision - --> ROOT/testdata/DivideBeforeMultiply.sol:LL:CC - | -LL | (1 / 2) * 3; - | ^^^^^^^^^^^ - | - = help: https://book.getfoundry.sh/reference/forge/forge-lint#divide-before-multiply + --> ROOT/testdata/DivideBeforeMultiply.sol:LL:CC + | +3 | (1 / 2) * 3; + | ----------- + | + = help: https://book.getfoundry.sh/reference/forge/forge-lint#divide-before-multiply warning[divide-before-multiply]: multiplication should occur before division to avoid loss of precision - --> ROOT/testdata/DivideBeforeMultiply.sol:LL:CC - | -LL | ((1 / 2) * 3) * 4; - | ^^^^^^^^^^^ - | - = help: https://book.getfoundry.sh/reference/forge/forge-lint#divide-before-multiply + --> ROOT/testdata/DivideBeforeMultiply.sol:LL:CC + | +5 | ((1 / 2) * 3) * 4; + | ----------- + | + = help: https://book.getfoundry.sh/reference/forge/forge-lint#divide-before-multiply warning[divide-before-multiply]: multiplication should occur before division to avoid loss of precision - --> ROOT/testdata/DivideBeforeMultiply.sol:LL:CC - | -LL | ((1 * 2) / 3) * 4; - | ^^^^^^^^^^^^^^^^^ - | - = help: https://book.getfoundry.sh/reference/forge/forge-lint#divide-before-multiply + --> ROOT/testdata/DivideBeforeMultiply.sol:LL:CC + | +6 | ((1 * 2) / 3) * 4; + | ----------------- + | + = help: https://book.getfoundry.sh/reference/forge/forge-lint#divide-before-multiply warning[divide-before-multiply]: multiplication should occur before division to avoid loss of precision - --> ROOT/testdata/DivideBeforeMultiply.sol:LL:CC - | -LL | (1 / 2 / 3) * 4; - | ^^^^^^^^^^^^^^^ - | - = help: https://book.getfoundry.sh/reference/forge/forge-lint#divide-before-multiply + --> ROOT/testdata/DivideBeforeMultiply.sol:LL:CC + | +7 | (1 / 2 / 3) * 4; + | --------------- + | + = help: https://book.getfoundry.sh/reference/forge/forge-lint#divide-before-multiply warning[divide-before-multiply]: multiplication should occur before division to avoid loss of precision - --> ROOT/testdata/DivideBeforeMultiply.sol:LL:CC - | -LL | (1 / (2 + 3)) * 4; - | ^^^^^^^^^^^^^^^^^ - | - = help: https://book.getfoundry.sh/reference/forge/forge-lint#divide-before-multiply + --> ROOT/testdata/DivideBeforeMultiply.sol:LL:CC + | +8 | (1 / (2 + 3)) * 4; + | ----------------- + | + = help: https://book.getfoundry.sh/reference/forge/forge-lint#divide-before-multiply warning[divide-before-multiply]: multiplication should occur before division to avoid loss of precision --> ROOT/testdata/DivideBeforeMultiply.sol:LL:CC | -LL | 1 / ((2 / 3) * 3); - | ^^^^^^^^^^^ +15 | 1 / ((2 / 3) * 3); + | ----------- | = help: https://book.getfoundry.sh/reference/forge/forge-lint#divide-before-multiply From 4cd968ba7f3d847f42f4c243a550b7b22bd32885 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Wed, 31 Dec 2025 23:32:30 +0700 Subject: [PATCH 173/232] Update crates/evm/evm/src/executors/corpus.rs Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- crates/evm/evm/src/executors/corpus.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/evm/evm/src/executors/corpus.rs b/crates/evm/evm/src/executors/corpus.rs index 92eb4452ce802..f8333418caec3 100644 --- a/crates/evm/evm/src/executors/corpus.rs +++ b/crates/evm/evm/src/executors/corpus.rs @@ -209,7 +209,7 @@ impl CorpusManager { }) }; - 'corpus_replay: for entry in std::fs::read_dir(corpus_dir)? { + 'corpus_replay: for entry in std::fs::read_dir(&canonical_corpus_dir)? { let path = entry?.path(); // Canonicalize the candidate path, skip if it cannot be canonicalized (e.g. broken symlink) let canonical_path = match path.canonicalize() { From e614a6319ddbb974c94e478fc657b0f2fe9b4da9 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Thu, 1 Jan 2026 00:41:48 +0700 Subject: [PATCH 174/232] Foundry/master test ux (#295) * Update ci.yml Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update ci.yml (#211) This pull request updates the Rust version in the CircleCI workflow to 1.89.0. This is a good maintenance task to keep the CI environment up-to-date. I have one suggestion regarding the Docker image tag to potentially simplify future maintenance by automatically adopting patch releases. Overall, the change is correct and beneficial. Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update test.yml (#250) CI: Include the 'main' branch in the push event triggers for the test workflow Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --------- Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- .circleci/ci.yml | 31 +++++++++++++++++++++++++++++ .circleci/config.yml | 32 ++++++++++++++++++++++++++++++ .github/workflows/docker-image.yml | 21 ++++++++++++++++++++ 3 files changed, 84 insertions(+) create mode 100644 .circleci/ci.yml create mode 100644 .circleci/config.yml create mode 100644 .github/workflows/docker-image.yml diff --git a/.circleci/ci.yml b/.circleci/ci.yml new file mode 100644 index 0000000000000..1b5df6d6e668e --- /dev/null +++ b/.circleci/ci.yml @@ -0,0 +1,31 @@ +version: 2.1 +jobs: + build-and-test: + docker: + - image: cimg/rust:1.89.0 + steps: + - checkout + - restore_cache: + keys: + - v1-cargo-{{ checksum "Cargo.lock" }} + - v1-cargo- + - run: + name: "Check formatting" + command: cargo fmt -- --check + - run: + name: "Run tests" + command: cargo test + - save_cache: + key: v1-cargo-{{ checksum "Cargo.lock" }} + paths: + - "~/.cargo/bin" + - "~/.cargo/registry/index" + - "~/.cargo/registry/cache" + - "~/.cargo/git/db" + - "target" + - run: + name: "Check formatting" + command: cargo fmt -- --check + - run: + name: "Run tests" + command: cargo test diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000000000..76b2889f1c4b2 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,32 @@ +# Use the latest 2.1 version of CircleCI pipeline process engine. +# See: https://circleci.com/docs/configuration-reference +version: 2.1 + +# Define a job to be invoked later in a workflow. +# See: https://circleci.com/docs/jobs-steps/#jobs-overview & https://circleci.com/docs/configuration-reference/#jobs +jobs: + say-hello: + # Specify the execution environment. You can specify an image from Docker Hub or use one of our convenience images from CircleCI's Developer Hub. + # See: https://circleci.com/docs/executor-intro/ & https://circleci.com/docs/configuration-reference/#executor-job + docker: + # Specify the version you desire here + # See: https://circleci.com/developer/images/image/cimg/base + - image: cimg/base:current + + # Add steps to the job + # See: https://circleci.com/docs/jobs-steps/#steps-overview & https://circleci.com/docs/configuration-reference/#steps + steps: + # Checkout the code as the first step. + - checkout + - run: + name: "Say hello" + command: "echo Hello, World!" + +# Orchestrate jobs using workflows +# See: https://circleci.com/docs/workflows/ & https://circleci.com/docs/configuration-reference/#workflows +workflows: + say-hello-workflow: # This is the name of the workflow, feel free to change it to better match your workflow. + # Inside the workflow, you define the jobs you want to run. + jobs: + - say-hello + diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml new file mode 100644 index 0000000000000..e0c9c518e8748 --- /dev/null +++ b/.github/workflows/docker-image.yml @@ -0,0 +1,21 @@ +name: Docker Image CI + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + +permissions: + contents: read + +jobs: + + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Build the Docker image + run: docker build . --file Dockerfile --tag my-image-name:${{ github.sha }} From 4f1dfb9fc6b58ab9b248af34e359f5600a743381 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Thu, 1 Jan 2026 01:40:10 +0700 Subject: [PATCH 175/232] fix(fmt): handle trailing coments between base contracts (#296) (#299) @0xrusowsky @Dargon789 fix(fmt): handle trailing coments between base contracts Revert 142 master (#296) * Create ci_cargo.yml (#72) * Create config.yml * Rename ci_cargo.yml to cargo.yml * fix(fmt): handle trailing coments between base contracts (#12127) * fix(fmt): account for ternary operators when estimating size * fix(fmt): handle comments between inherited base contracts * test: layout + base inheritance * Revert "fix(fmt): handle trailing coments between base contracts (#12127)" This reverts commit b8b5fbb83fa2436063cebc34ddf900abc972b11d. * Update cargo.yml (#172) CI/CD Configuration Update: The CircleCI configuration file, .circleci/cargo.yml, has been updated to use a newer version of the Rust Docker image. Rust Toolchain Version Bump: The cimg/rust Docker image version has been incremented from 1.88.0 to 1.89.0, ensuring builds and tests run with the latest stable Rust toolchain. * Fix cloning of compiler settings for Vyper input Replace context.clone().compiler_settings.vyper with context.compiler_settings.vyper.clone() to avoid unnecessary cloning of the entire VerificationContext. This reduces memory allocations when creating VyperInput instances. Applied to both etherscan and sourcify verification providers. * Remove duplicate logic in TxSigner::address() implementations --------- Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: 0xrusowsky <90208954+0xrusowsky@users.noreply.github.com> Co-authored-by: Gengar Co-authored-by: Aganis --- .circleci/config.yml | 10 +++++----- crates/wallets/src/signer.rs | 2 +- crates/wallets/src/wallet_browser/signer.rs | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 76b2889f1c4b2..4168efef0971f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,20 +1,20 @@ # Use the latest 2.1 version of CircleCI pipeline process engine. -# See: https://circleci.com/docs/configuration-reference +# See: https://circleci.com/docs/reference/configuration-reference version: 2.1 # Define a job to be invoked later in a workflow. -# See: https://circleci.com/docs/jobs-steps/#jobs-overview & https://circleci.com/docs/configuration-reference/#jobs +# See: https://circleci.com/docs/guides/orchestrate/jobs-steps/#jobs-overview & https://circleci.com/docs/reference/configuration-reference/#jobs jobs: say-hello: # Specify the execution environment. You can specify an image from Docker Hub or use one of our convenience images from CircleCI's Developer Hub. - # See: https://circleci.com/docs/executor-intro/ & https://circleci.com/docs/configuration-reference/#executor-job + # See: https://circleci.com/docs/guides/execution-managed/executor-intro/ & https://circleci.com/docs/reference/configuration-reference/#executor-job docker: # Specify the version you desire here # See: https://circleci.com/developer/images/image/cimg/base - image: cimg/base:current # Add steps to the job - # See: https://circleci.com/docs/jobs-steps/#steps-overview & https://circleci.com/docs/configuration-reference/#steps + # See: https://circleci.com/docs/guides/orchestrate/jobs-steps/#steps-overview & https://circleci.com/docs/reference/configuration-reference/#steps steps: # Checkout the code as the first step. - checkout @@ -23,7 +23,7 @@ jobs: command: "echo Hello, World!" # Orchestrate jobs using workflows -# See: https://circleci.com/docs/workflows/ & https://circleci.com/docs/configuration-reference/#workflows +# See: https://circleci.com/docs/guides/orchestrate/workflows/ & https://circleci.com/docs/reference/configuration-reference/#workflows workflows: say-hello-workflow: # This is the name of the workflow, feel free to change it to better match your workflow. # Inside the workflow, you define the jobs you want to run. diff --git a/crates/wallets/src/signer.rs b/crates/wallets/src/signer.rs index 5a5c77c676587..8d50c03d1a90b 100644 --- a/crates/wallets/src/signer.rs +++ b/crates/wallets/src/signer.rs @@ -322,7 +322,7 @@ impl Signer for WalletSigner { #[async_trait] impl TxSigner for WalletSigner { fn address(&self) -> Address { - delegate!(self, inner => alloy_signer::Signer::address(inner)) + Signer::address(self) } async fn sign_transaction( diff --git a/crates/wallets/src/wallet_browser/signer.rs b/crates/wallets/src/wallet_browser/signer.rs index 1e3df775e2598..78cf166a35ad0 100644 --- a/crates/wallets/src/wallet_browser/signer.rs +++ b/crates/wallets/src/wallet_browser/signer.rs @@ -177,7 +177,7 @@ impl Signer for BrowserSigner { #[async_trait] impl TxSigner for BrowserSigner { fn address(&self) -> Address { - self.address + Signer::address(self) } async fn sign_transaction( From 77200b02e604ea5c67643d6cc3c5931b58777b74 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Fri, 2 Jan 2026 01:54:09 +0700 Subject: [PATCH 176/232] Update CircleCI configuration for dev stage (#300) fix Automatic reruns provide a safety net for your CI/CD pipelines by automatically retrying failed steps and/or workflows. Automatic reruns help teams maintain productivity by reducing the need for manual intervention when steps and workflows fail due to temporary issues. Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- .circleci/dev_stage.yml | 50 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 .circleci/dev_stage.yml diff --git a/.circleci/dev_stage.yml b/.circleci/dev_stage.yml new file mode 100644 index 0000000000000..03e77d78fcc3c --- /dev/null +++ b/.circleci/dev_stage.yml @@ -0,0 +1,50 @@ +# ~/.circleci/config.yml +version: 2.1 + jobs: + my-job: + steps: + - run: echo "Hello, world!" + - run: + command: echo "This step will automatically rerun up to 3 times if it fails with a 10 second delay between attempts" + max_auto_reruns: 3 + auto_rerun_delay: 10s + + workflows: + dev_stage_pre-prod: + jobs: + - test_dev: + filters: # using regex filters requires the entire branch to match + branches: + only: # only branches matching the below regex filters will run + - dev + - /user-.*/ + - test_stage: + filters: + branches: + only: stage + - test_pre-prod: + filters: + branches: + only: /pre-prod(?:-.+)?$/ + + + build-test-deploy: + jobs: + - build: + filters: # required since `test` has tag filters AND requires `build` + tags: + only: /^config-test.*/ + - test: + requires: + - build + filters: # required since `deploy` has tag filters AND requires `test` + tags: + only: /^config-test.*/ + - deploy: + requires: + - test + filters: + tags: + only: /^config-test.*/ + branches: + ignore: /.*/ From a0c703a3761df9e10fbaa622c2b9d52239c630eb Mon Sep 17 00:00:00 2001 From: tskoyo Date: Thu, 25 Dec 2025 21:18:00 +0100 Subject: [PATCH 177/232] EIP-4788 implementation --- crates/cast/src/cmd/run.rs | 23 ++++++++++++++++++++-- crates/evm/evm/src/executors/trace.rs | 28 ++++++++++++++++++++++++++- 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/crates/cast/src/cmd/run.rs b/crates/cast/src/cmd/run.rs index 54894fc10b7ea..51a08274ee7cb 100644 --- a/crates/cast/src/cmd/run.rs +++ b/crates/cast/src/cmd/run.rs @@ -2,7 +2,7 @@ use crate::{debug::handle_traces, utils::apply_chain_and_block_specific_env_chan use alloy_consensus::Transaction; use alloy_network::{AnyNetwork, TransactionResponse}; use alloy_primitives::{ - Address, Bytes, U256, + Address, Bytes, FixedBytes, U256, map::{AddressSet, HashMap}, }; use alloy_provider::Provider; @@ -31,7 +31,7 @@ use foundry_evm::{ utils::configure_tx_env, }; use futures::TryFutureExt; -use revm::DatabaseRef; +use revm::{DatabaseRef, primitives::hardfork::SpecId}; /// CLI arguments for `cast run`. #[derive(Clone, Debug, Parser)] @@ -183,6 +183,8 @@ impl RunArgs { env.evm_env.cfg_env.limit_contract_code_size = None; env.evm_env.block_env.number = U256::from(tx_block_number); + let mut parent_beacon_block_root: FixedBytes<32> = FixedBytes::default(); + if let Some(block) = &block { env.evm_env.block_env.timestamp = U256::from(block.header.timestamp); env.evm_env.block_env.beneficiary = block.header.beneficiary; @@ -191,6 +193,16 @@ impl RunArgs { env.evm_env.block_env.basefee = block.header.base_fee_per_gas.unwrap_or_default(); env.evm_env.block_env.gas_limit = block.header.gas_limit; + if env.evm_env.cfg_env.spec >= SpecId::CANCUN { + if let Some(beacon_root) = block.header.parent_beacon_block_root { + parent_beacon_block_root = beacon_root; + } else { + return Err(eyre::eyre!( + "ParentBeaconBlockRoot is missing for Cancun or later blocks" + )); + } + } + // TODO: we need a smarter way to map the block to the corresponding evm_version for // commonly used chains if evm_version.is_none() { @@ -214,6 +226,7 @@ impl RunArgs { InternalTraceMode::None }) .with_state_changes(shell::verbosity() > 4); + let mut executor = TracingExecutor::new( env.clone(), fork, @@ -223,6 +236,12 @@ impl RunArgs { create2_deployer, None, )?; + + if parent_beacon_block_root != FixedBytes::default() { + let timestamp: u64 = env.evm_env.block_env.timestamp.try_into().unwrap_or(0); + executor.process_beacon_block_root(timestamp, parent_beacon_block_root)?; + } + let mut env = Env::new_with_spec_id( env.evm_env.cfg_env.clone(), env.evm_env.block_env.clone(), diff --git a/crates/evm/evm/src/executors/trace.rs b/crates/evm/evm/src/executors/trace.rs index d951dde0d6663..319e2ab495ca6 100644 --- a/crates/evm/evm/src/executors/trace.rs +++ b/crates/evm/evm/src/executors/trace.rs @@ -2,7 +2,7 @@ use crate::{ Env, executors::{Executor, ExecutorBuilder}, }; -use alloy_primitives::{Address, U256, map::HashMap}; +use alloy_primitives::{Address, FixedBytes, U256, address, map::HashMap}; use alloy_rpc_types::state::StateOverride; use eyre::Context; use foundry_compilers::artifacts::EvmVersion; @@ -92,6 +92,32 @@ impl TracingExecutor { let chain = env.tx.chain_id.unwrap().into(); Ok((env, fork, chain, networks)) } + + /// Processes the beacon block root by storing it in the appropriate storage slots. + pub fn process_beacon_block_root( + &mut self, + block_timestamp: u64, + beacon_root: FixedBytes<32>, + ) -> eyre::Result<()> { + const BEACON_ROOTS_ADDRESS: Address = address!("000F3df6D732807Ef1319fB7B8bB8522d0Beac02"); + const HISTORY_BUFFER_LENGTH: u64 = 8191; + + let timestamp_index = block_timestamp % HISTORY_BUFFER_LENGTH; + let root_index = timestamp_index + HISTORY_BUFFER_LENGTH; + + let timestamp_slot = U256::from(timestamp_index); + let root_slot = U256::from(root_index); + + self.set_storage_slot(BEACON_ROOTS_ADDRESS, timestamp_slot, U256::from(block_timestamp))?; + + self.set_storage_slot( + BEACON_ROOTS_ADDRESS, + root_slot, + U256::from_be_bytes(beacon_root.into()), + )?; + + Ok(()) + } } impl Deref for TracingExecutor { From 61646b8242c176937abf134364180a44951ae4a2 Mon Sep 17 00:00:00 2001 From: tskoyo Date: Sat, 27 Dec 2025 14:55:45 +0100 Subject: [PATCH 178/232] formatting --- crates/cast/src/cmd/run.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/cast/src/cmd/run.rs b/crates/cast/src/cmd/run.rs index 51a08274ee7cb..6152f5b6978a6 100644 --- a/crates/cast/src/cmd/run.rs +++ b/crates/cast/src/cmd/run.rs @@ -226,7 +226,6 @@ impl RunArgs { InternalTraceMode::None }) .with_state_changes(shell::verbosity() > 4); - let mut executor = TracingExecutor::new( env.clone(), fork, From 242e19c664797b1b9a0de672120b9eebe4287dbf Mon Sep 17 00:00:00 2001 From: tskoyo Date: Thu, 1 Jan 2026 07:29:18 +0100 Subject: [PATCH 179/232] add beacon block root tests --- crates/cast/src/cmd/run.rs | 14 ++++---------- crates/cast/tests/cli/main.rs | 28 ++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/crates/cast/src/cmd/run.rs b/crates/cast/src/cmd/run.rs index 6152f5b6978a6..8336714a66bb2 100644 --- a/crates/cast/src/cmd/run.rs +++ b/crates/cast/src/cmd/run.rs @@ -2,7 +2,7 @@ use crate::{debug::handle_traces, utils::apply_chain_and_block_specific_env_chan use alloy_consensus::Transaction; use alloy_network::{AnyNetwork, TransactionResponse}; use alloy_primitives::{ - Address, Bytes, FixedBytes, U256, + Address, Bytes, U256, map::{AddressSet, HashMap}, }; use alloy_provider::Provider; @@ -183,7 +183,7 @@ impl RunArgs { env.evm_env.cfg_env.limit_contract_code_size = None; env.evm_env.block_env.number = U256::from(tx_block_number); - let mut parent_beacon_block_root: FixedBytes<32> = FixedBytes::default(); + let mut parent_beacon_block_root = None; if let Some(block) = &block { env.evm_env.block_env.timestamp = U256::from(block.header.timestamp); @@ -194,13 +194,7 @@ impl RunArgs { env.evm_env.block_env.gas_limit = block.header.gas_limit; if env.evm_env.cfg_env.spec >= SpecId::CANCUN { - if let Some(beacon_root) = block.header.parent_beacon_block_root { - parent_beacon_block_root = beacon_root; - } else { - return Err(eyre::eyre!( - "ParentBeaconBlockRoot is missing for Cancun or later blocks" - )); - } + parent_beacon_block_root = block.header.parent_beacon_block_root; } // TODO: we need a smarter way to map the block to the corresponding evm_version for @@ -236,7 +230,7 @@ impl RunArgs { None, )?; - if parent_beacon_block_root != FixedBytes::default() { + if let Some(parent_beacon_block_root) = parent_beacon_block_root { let timestamp: u64 = env.evm_env.block_env.timestamp.try_into().unwrap_or(0); executor.process_beacon_block_root(timestamp, parent_beacon_block_root)?; } diff --git a/crates/cast/tests/cli/main.rs b/crates/cast/tests/cli/main.rs index b776370d2ac4d..c4a809f6c065c 100644 --- a/crates/cast/tests/cli/main.rs +++ b/crates/cast/tests/cli/main.rs @@ -2954,6 +2954,34 @@ Traces: "#]]); }); +// tests that displays a sample beacon block traces in Cancun +// https://github.com/foundry-rs/foundry/issues/12435 +casttest!(test_beacon_block_root_in_cancun, |prj, cmd| { + prj.clear(); + let eth_rpc_url = next_http_rpc_endpoint(); + cmd.args([ + "run", + "0xae290fe8c89c3e83dff20eeb2b8e3261bcdce0d66441c7056918dfb5fafe6d96", + "--rpc-url", + eth_rpc_url.as_str(), + ]) + .assert_success() + .stdout_eq(str![[r#" +Executing previous transactions from the block. +Traces: + [45054] 0xB731392c0EB5BF2092f9f7B520DA551f70Ea9131::Claim{value: 46698476594582387}() + ├─ [4320] 0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02::00000000(00000000000000000000000000000000000000000000000069091d4b) [staticcall] + │ └─ ← [Return] 0x70c7855161ec07af782df915fb3e81702df40f34972da3d740cdfc132ac926f6 + ├─ emit NvStuck(param0: 0x6e6C36B970f8862bA3F148DEdAB8F98f5ed8b426, param1: 46698476594582387 [4.669e16], param2: 1762205003 [1.762e9]) + └─ ← [Stop] + + +Transaction successfully executed. +[GAS] + +"#]]); +}); + // tests that displays a sample contract artifact // casttest!(fetch_artifact_from_etherscan, |_prj, cmd| { From 4e7adcda7260affcadf032000bf3a9a05781c48e Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Sat, 3 Jan 2026 01:31:13 +0700 Subject: [PATCH 180/232] Update crates/evm/evm/src/executors/trace.rs Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- crates/evm/evm/src/executors/trace.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/evm/evm/src/executors/trace.rs b/crates/evm/evm/src/executors/trace.rs index 319e2ab495ca6..7b63c019e848c 100644 --- a/crates/evm/evm/src/executors/trace.rs +++ b/crates/evm/evm/src/executors/trace.rs @@ -100,7 +100,7 @@ impl TracingExecutor { beacon_root: FixedBytes<32>, ) -> eyre::Result<()> { const BEACON_ROOTS_ADDRESS: Address = address!("000F3df6D732807Ef1319fB7B8bB8522d0Beac02"); - const HISTORY_BUFFER_LENGTH: u64 = 8191; + const HISTORY_BUFFER_LENGTH: u64 = 8192; let timestamp_index = block_timestamp % HISTORY_BUFFER_LENGTH; let root_index = timestamp_index + HISTORY_BUFFER_LENGTH; From 87051b31120d54da1bb40aba4ab5bf4f8a26b217 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Sat, 3 Jan 2026 01:31:54 +0700 Subject: [PATCH 181/232] Update crates/cast/src/cmd/run.rs Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- crates/cast/src/cmd/run.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cast/src/cmd/run.rs b/crates/cast/src/cmd/run.rs index 8336714a66bb2..b65101f5db80d 100644 --- a/crates/cast/src/cmd/run.rs +++ b/crates/cast/src/cmd/run.rs @@ -231,7 +231,7 @@ impl RunArgs { )?; if let Some(parent_beacon_block_root) = parent_beacon_block_root { - let timestamp: u64 = env.evm_env.block_env.timestamp.try_into().unwrap_or(0); + let timestamp: u64 = env.evm_env.block_env.timestamp.try_into().wrap_err("failed to convert block timestamp to u64")?; executor.process_beacon_block_root(timestamp, parent_beacon_block_root)?; } From 0303c65d2e2c0735b4c24da45c2038f43372108f Mon Sep 17 00:00:00 2001 From: "snyk-io[bot]" <141718529+snyk-io[bot]@users.noreply.github.com> Date: Sun, 4 Jan 2026 15:58:06 +0000 Subject: [PATCH 182/232] feat: upgrade @types/node from 24.10.4 to 25.0.2 Snyk has created this PR to upgrade @types/node from 24.10.4 to 25.0.2. See this package in npm: @types/node See this project in Snyk: https://app.snyk.io/org/dargon789/project/8da85645-409e-46fa-bd46-9b58e7905fb8?utm_source=github-cloud-app&utm_medium=referral&page=upgrade-pr --- npm/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/npm/package.json b/npm/package.json index 2362816053f8c..d596a7930b609 100644 --- a/npm/package.json +++ b/npm/package.json @@ -8,7 +8,7 @@ }, "dependencies": { "@types/bun": "^1.3.1", - "@types/node": "^24.9.1", + "@types/node": "^25.0.2", "bun": "^1.3.1", "typescript": "^5.9.3" }, From 43cd8245ddb3c6f14707ea5b80dfc71d6333e69b Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Wed, 7 Jan 2026 17:20:33 +0700 Subject: [PATCH 183/232] fix: `svm fails to download solc 0.8.33 on linux/arm64`, bump `svm-rs` (#13007) (#309) bump svm-rs Co-authored-by: zerosnacks <95942363+zerosnacks@users.noreply.github.com> --- Cargo.lock | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8f5f65ef4645d..7b4472f3e5388 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3665,7 +3665,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -3970,7 +3970,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -5409,8 +5409,8 @@ dependencies = [ "libc", "log", "rustversion", - "windows-link 0.2.1", - "windows-result 0.4.1", + "windows-link 0.1.3", + "windows-result 0.3.4", ] [[package]] @@ -5801,7 +5801,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.6.1", + "socket2 0.5.10", "system-configuration", "tokio", "tower-service", @@ -6178,7 +6178,7 @@ checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" dependencies = [ "hermit-abi", "libc", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -6924,7 +6924,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -8074,7 +8074,7 @@ dependencies = [ "quinn-udp", "rustc-hash", "rustls", - "socket2 0.6.1", + "socket2 0.5.10", "thiserror 2.0.17", "tokio", "tracing", @@ -8111,9 +8111,9 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.6.1", + "socket2 0.5.10", "tracing", - "windows-sys 0.60.2", + "windows-sys 0.59.0", ] [[package]] @@ -8920,7 +8920,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.11.0", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -9716,7 +9716,7 @@ dependencies = [ "solar-config", "solar-data-structures", "solar-macros", - "thiserror 2.0.17", + "thiserror 1.0.69", "tracing", "unicode-width 0.2.0", ] @@ -10042,9 +10042,9 @@ dependencies = [ [[package]] name = "svm-rs" -version = "0.5.22" +version = "0.5.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "909e8ff825120cd2b34ceb236ab72e2a7f74b1d3a86c247936c8ff7a80c5d408" +checksum = "415b159b54c22d9810087f0991371fd6242a912673e982a7c4ca8ea122f7e00a" dependencies = [ "const-hex", "dirs", @@ -10054,7 +10054,7 @@ dependencies = [ "serde_json", "sha2", "tempfile", - "thiserror 2.0.17", + "thiserror 1.0.69", "url", "zip", ] @@ -10168,7 +10168,7 @@ dependencies = [ "getrandom 0.3.4", "once_cell", "rustix 1.1.3", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -10208,7 +10208,7 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8c27177b12a6399ffc08b98f76f7c9a1f4fe9fc967c784c5a071fa8d93cf7e1" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -11520,7 +11520,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] From 6067ae2b1f3cf645627443274bae23e1d0f5a935 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Wed, 7 Jan 2026 18:22:30 +0700 Subject: [PATCH 184/232] Ethereumjs/master (#310) * Potential fix for code scanning alert no. 19: Workflow does not contain permissions Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 61: Workflow does not contain permissions Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 74: Artifact poisoning Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Create config.yml (#105) * Create cargo.yml (#106) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Delete .github/workflows/docker-image.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Rename ci_cargo.yml to cargo.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * fix(fmt): handle trailing coments between base contracts (#12127) * fix(fmt): account for ternary operators when estimating size * fix(fmt): handle comments between inherited base contracts * test: layout + base inheritance * Revert "fix(fmt): handle trailing coments between base contracts (#12127)" This reverts commit b8b5fbb83fa2436063cebc34ddf900abc972b11d. * Update cargo.yml (#172) CI/CD Configuration Update: The CircleCI configuration file, .circleci/cargo.yml, has been updated to use a newer version of the Rust Docker image. Rust Toolchain Version Bump: The cimg/rust Docker image version has been incremented from 1.88.0 to 1.89.0, ensuring builds and tests run with the latest stable Rust toolchain. Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Revert "Create cargo.yml (#106)" This reverts commit 251a2b4fce0c50e3426ffb2022d9abef5b948fa9. * Create cargo.yml (#213) https://github.com/apps/gemini-code-assist Code Review This pull request introduces a CircleCI workflow to automate formatting checks and tests. My review has identified two main issues in the configuration: redundant steps that would unnecessarily increase job execution time, and a mismatch between the Rust version in the CI environment and the one specified in the project's Cargo.toml. I've provided suggestions to fix these issues for a more efficient and consistent CI process. Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Create docker.yml Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Remove duplicate logic in TxSigner::address() implementations * fix(fmt): handle trailing coments between base contracts (#296) @0xrusowsky @Dargon789 fix(fmt): handle trailing coments between base contracts Revert 142 master (#296) * Create ci_cargo.yml (#72) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Create config.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Rename ci_cargo.yml to cargo.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * fix(fmt): handle trailing coments between base contracts (#12127) * fix(fmt): account for ternary operators when estimating size * fix(fmt): handle comments between inherited base contracts * test: layout + base inheritance * Revert "fix(fmt): handle trailing coments between base contracts (#12127)" This reverts commit b8b5fbb83fa2436063cebc34ddf900abc972b11d. * Update cargo.yml (#172) CI/CD Configuration Update: The CircleCI configuration file, .circleci/cargo.yml, has been updated to use a newer version of the Rust Docker image. Rust Toolchain Version Bump: The cimg/rust Docker image version has been incremented from 1.88.0 to 1.89.0, ensuring builds and tests run with the latest stable Rust toolchain. Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Fix cloning of compiler settings for Vyper input Replace context.clone().compiler_settings.vyper with context.compiler_settings.vyper.clone() to avoid unnecessary cloning of the entire VerificationContext. This reduces memory allocations when creating VyperInput instances. Applied to both etherscan and sourcify verification providers. * Remove duplicate logic in TxSigner::address() implementations --------- Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: 0xrusowsky <90208954+0xrusowsky@users.noreply.github.com> Co-authored-by: Gengar Co-authored-by: Aganis --------- Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Co-authored-by: 0xrusowsky <90208954+0xrusowsky@users.noreply.github.com> Co-authored-by: Aganis Co-authored-by: Gengar --- .github/workflows/docker-image.yml | 21 --------------------- 1 file changed, 21 deletions(-) delete mode 100644 .github/workflows/docker-image.yml diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml deleted file mode 100644 index e0c9c518e8748..0000000000000 --- a/.github/workflows/docker-image.yml +++ /dev/null @@ -1,21 +0,0 @@ -name: Docker Image CI - -on: - push: - branches: [ "master" ] - pull_request: - branches: [ "master" ] - -permissions: - contents: read - -jobs: - - build: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - name: Build the Docker image - run: docker build . --file Dockerfile --tag my-image-name:${{ github.sha }} From 784a3857a84dfa2a1bd8604dafc4a783d05e0c64 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Wed, 7 Jan 2026 21:54:11 +0700 Subject: [PATCH 185/232] Forge/master (#311) * Potential fix for code scanning alert no. 19: Workflow does not contain permissions Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 61: Workflow does not contain permissions Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 74: Artifact poisoning Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Create config.yml (#105) * Create cargo.yml (#106) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Delete .github/workflows/docker-image.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Rename ci_cargo.yml to cargo.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * fix(fmt): handle trailing coments between base contracts (#12127) * fix(fmt): account for ternary operators when estimating size * fix(fmt): handle comments between inherited base contracts * test: layout + base inheritance * Revert "fix(fmt): handle trailing coments between base contracts (#12127)" This reverts commit b8b5fbb83fa2436063cebc34ddf900abc972b11d. * Update cargo.yml (#172) CI/CD Configuration Update: The CircleCI configuration file, .circleci/cargo.yml, has been updated to use a newer version of the Rust Docker image. Rust Toolchain Version Bump: The cimg/rust Docker image version has been incremented from 1.88.0 to 1.89.0, ensuring builds and tests run with the latest stable Rust toolchain. Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Revert "Create cargo.yml (#106)" This reverts commit 251a2b4fce0c50e3426ffb2022d9abef5b948fa9. * Create cargo.yml (#213) https://github.com/apps/gemini-code-assist Code Review This pull request introduces a CircleCI workflow to automate formatting checks and tests. My review has identified two main issues in the configuration: redundant steps that would unnecessarily increase job execution time, and a mismatch between the Rust version in the CI environment and the one specified in the project's Cargo.toml. I've provided suggestions to fix these issues for a more efficient and consistent CI process. Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Create ci-web3-gamefi.yml (#217) Introduce a basic CircleCI pipeline for the web3 GameFi project, providing a custom Docker executor and a stub job within a workflow. CI: Add CircleCI config file ci-web3-gamefi.yml with version 2.1 pipeline Define a custom executor using the cimg/base:stable Docker image with Docker Hub credentials Create a web3-defi-game-project- job and integrate it into a my-custom-workflow Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Remove duplicate logic in TxSigner::address() implementations * fix(fmt): handle trailing coments between base contracts (#296) @0xrusowsky @Dargon789 fix(fmt): handle trailing coments between base contracts Revert 142 master (#296) * Create ci_cargo.yml (#72) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Create config.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Rename ci_cargo.yml to cargo.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * fix(fmt): handle trailing coments between base contracts (#12127) * fix(fmt): account for ternary operators when estimating size * fix(fmt): handle comments between inherited base contracts * test: layout + base inheritance * Revert "fix(fmt): handle trailing coments between base contracts (#12127)" This reverts commit b8b5fbb83fa2436063cebc34ddf900abc972b11d. * Update cargo.yml (#172) CI/CD Configuration Update: The CircleCI configuration file, .circleci/cargo.yml, has been updated to use a newer version of the Rust Docker image. Rust Toolchain Version Bump: The cimg/rust Docker image version has been incremented from 1.88.0 to 1.89.0, ensuring builds and tests run with the latest stable Rust toolchain. Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Fix cloning of compiler settings for Vyper input Replace context.clone().compiler_settings.vyper with context.compiler_settings.vyper.clone() to avoid unnecessary cloning of the entire VerificationContext. This reduces memory allocations when creating VyperInput instances. Applied to both etherscan and sourcify verification providers. * Remove duplicate logic in TxSigner::address() implementations --------- Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: 0xrusowsky <90208954+0xrusowsky@users.noreply.github.com> Co-authored-by: Gengar Co-authored-by: Aganis --------- Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Co-authored-by: 0xrusowsky <90208954+0xrusowsky@users.noreply.github.com> Co-authored-by: Aganis Co-authored-by: Gengar From f61d8e8595b855634491413defc8508e84e0dede Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Thu, 8 Jan 2026 02:55:41 +0700 Subject: [PATCH 186/232] Update dev_stage.yml (#313) (#315) * Update dev_stage.yml (#313) Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update .circleci/dev_stage.yml Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --------- Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> --- .circleci/dev_stage.yml | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/.circleci/dev_stage.yml b/.circleci/dev_stage.yml index 03e77d78fcc3c..5ba351727d22b 100644 --- a/.circleci/dev_stage.yml +++ b/.circleci/dev_stage.yml @@ -1,5 +1,25 @@ -# ~/.circleci/config.yml +# Use the latest 2.1 version of CircleCI pipeline process engine. +# See: https://circleci.com/docs/configuration-reference + version: 2.1 +executors: + my-custom-executor: + docker: + - image: cimg/base:stable +jobs: + web3-defi-game-project-: + + executor: my-custom-executor + steps: + - checkout + - run: | + # echo Hello, World! + +workflows: + my-custom-workflow: + jobs: + - web3-defi-game-project- + jobs: my-job: steps: From c97d4fa09efa5908766756c157ab34b6aee9d81f Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Thu, 8 Jan 2026 03:53:35 +0700 Subject: [PATCH 187/232] Foundry/main (#316) * chore(deps): bump the cargo group across 1 directory with 2 updates Bumps the cargo group with 2 updates in the / directory: [tracing-subscriber](https://github.com/tokio-rs/tracing) and [ammonia](https://github.com/rust-ammonia/ammonia). Updates `tracing-subscriber` from 0.3.19 to 0.3.20 - [Release notes](https://github.com/tokio-rs/tracing/releases) - [Commits](https://github.com/tokio-rs/tracing/compare/tracing-subscriber-0.3.19...tracing-subscriber-0.3.20) Updates `ammonia` from 4.1.0 to 4.1.2 - [Release notes](https://github.com/rust-ammonia/ammonia/releases) - [Changelog](https://github.com/rust-ammonia/ammonia/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-ammonia/ammonia/compare/v4.1.0...v4.1.2) --- updated-dependencies: - dependency-name: tracing-subscriber dependency-version: 0.3.20 dependency-type: direct:production dependency-group: cargo - dependency-name: ammonia dependency-version: 4.1.2 dependency-type: indirect dependency-group: cargo ... Signed-off-by: dependabot[bot] * Update crates/verify/src/provider.rs Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update crates/doc/src/writer/as_doc.rs Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update as_doc.rs (#235) Tidy up formatting in as_doc.rs by removing extraneous blank lines in the Document::as_doc implementation Enhancements: Remove unnecessary blank line before initializing bases Remove unnecessary blank line before writing state variables Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --------- Signed-off-by: dependabot[bot] Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> From cc27594b6fbab226fdd556eb67fbdd6b19976577 Mon Sep 17 00:00:00 2001 From: Matt D Date: Thu, 8 Jan 2026 17:16:11 +0800 Subject: [PATCH 188/232] chore: ignore RUSTSEC (#13011) * update deny for CI * Update more --- deny.toml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/deny.toml b/deny.toml index 854f33033ed2c..6b041e529e801 100644 --- a/deny.toml +++ b/deny.toml @@ -9,8 +9,10 @@ ignore = [ "RUSTSEC-2024-0436", # https://rustsec.org/advisories/RUSTSEC-2024-0437 protobuf! Crash due to uncontrolled recursion in protobuf crate. "RUSTSEC-2024-0437", - # https://rustsec.org/advisories/RUSTSEC-2025-0137 `reciprocal_mg10` OOB, unused - "RUSTSEC-2025-0137", + # https://rustsec.org/advisories/RUSTSEC-2025-0141 bincode is unmaintained, need to transition all deps to wincode first + "RUSTSEC-2025-0141", + # https://rustsec.org/advisories/RUSTSEC-2026-0002 lru unused directly: + "RUSTSEC-2026-0002", ] # This section is considered when running `cargo deny check bans`. From 39fb603d5a427c51393a91f36f447d4ff1413a8f Mon Sep 17 00:00:00 2001 From: onbjerg Date: Thu, 8 Jan 2026 10:50:39 +0100 Subject: [PATCH 189/232] chore(chisel): rm dead code (#13014) --- crates/chisel/src/source.rs | 47 ------------------------------------- 1 file changed, 47 deletions(-) diff --git a/crates/chisel/src/source.rs b/crates/chisel/src/source.rs index 576f36eab02f3..7eedb31923439 100644 --- a/crates/chisel/src/source.rs +++ b/crates/chisel/src/source.rs @@ -567,20 +567,6 @@ impl SessionSource { self.clear_output(); } - /// Clear the global-level code . - pub fn clear_global(&mut self) -> &mut Self { - String::clear(&mut self.global_code); - self.clear_output(); - self - } - - /// Clear the contract-level code . - pub fn clear_contract(&mut self) -> &mut Self { - String::clear(&mut self.contract_code); - self.clear_output(); - self - } - /// Clear the `run()` function code. pub fn clear_run(&mut self) -> &mut Self { String::clear(&mut self.run_code); @@ -694,39 +680,6 @@ impl SessionSource { Ok(intermediate_output) } - /// Construct the source as a valid Forge script. - pub fn to_script_source(&self) -> String { - let Self { - contract_name, - global_code, - contract_code: top_level_code, - run_code, - config, - .. - } = self; - - let script_import = - if !config.no_vm { "import {Script} from \"forge-std/Script.sol\";\n" } else { "" }; - - format!( - r#" -// SPDX-License-Identifier: UNLICENSED -pragma solidity 0; - -{script_import} -{global_code} - -contract {contract_name} is Script {{ - {top_level_code} - - /// @notice Script entry point - function run() public {{ - {run_code} - }} -}}"#, - ) - } - /// Construct the REPL source. pub fn to_repl_source(&self) -> String { let Self { From a1a18dfb7cfbd5201373093e16cd79386acabfaf Mon Sep 17 00:00:00 2001 From: onbjerg Date: Thu, 8 Jan 2026 10:50:54 +0100 Subject: [PATCH 190/232] chore(cli): rm dead code (#13015) --- crates/cli/src/opts/evm.rs | 8 ------- crates/cli/src/utils/cmd.rs | 46 +------------------------------------ 2 files changed, 1 insertion(+), 53 deletions(-) diff --git a/crates/cli/src/opts/evm.rs b/crates/cli/src/opts/evm.rs index b1a55d5cbae03..6499d693ddf40 100644 --- a/crates/cli/src/opts/evm.rs +++ b/crates/cli/src/opts/evm.rs @@ -2,7 +2,6 @@ use alloy_primitives::{Address, B256, U256}; use clap::Parser; -use eyre::ContextCompat; use foundry_config::{ Chain, Config, figment::{ @@ -260,13 +259,6 @@ pub struct EnvArgs { pub enable_tx_gas_limit: bool, } -impl EvmArgs { - /// Ensures that fork url exists and returns its reference. - pub fn ensure_fork_url(&self) -> eyre::Result<&String> { - self.fork_url.as_ref().wrap_err("Missing `--fork-url` field.") - } -} - /// We have to serialize chain IDs and not names because when extracting an EVM `Env`, it expects /// `chain_id` to be `u64`. fn id(chain: &Option, s: S) -> Result { diff --git a/crates/cli/src/utils/cmd.rs b/crates/cli/src/utils/cmd.rs index ec483bca88359..b0f3661881843 100644 --- a/crates/cli/src/utils/cmd.rs +++ b/crates/cli/src/utils/cmd.rs @@ -2,10 +2,7 @@ use alloy_json_abi::JsonAbi; use eyre::{Result, WrapErr}; use foundry_common::{TestFunctionExt, fs, fs::json_files, selectors::SelectorKind, shell}; use foundry_compilers::{ - Artifact, ArtifactId, ProjectCompileOutput, - artifacts::{CompactBytecode, Settings}, - cache::{CacheEntry, CompilerCache}, - utils::read_json_file, + Artifact, ArtifactId, ProjectCompileOutput, artifacts::CompactBytecode, utils::read_json_file, }; use foundry_config::{Chain, Config, NamedChain, error::ExtractConfigError, figment::Figment}; use foundry_evm::{ @@ -65,47 +62,6 @@ pub fn find_contract_artifacts( Ok((abi, bin, id)) } -/// Helper function for finding a contract by ContractName -// TODO: Is there a better / more ergonomic way to get the artifacts given a project and a -// contract name? -pub fn get_cached_entry_by_name( - cache: &CompilerCache, - name: &str, -) -> Result<(PathBuf, CacheEntry)> { - let mut cached_entry = None; - let mut alternatives = Vec::new(); - - for (abs_path, entry) in &cache.files { - for artifact_name in entry.artifacts.keys() { - if artifact_name == name { - if cached_entry.is_some() { - eyre::bail!( - "contract with duplicate name `{}`. please pass the path instead", - name - ) - } - cached_entry = Some((abs_path.to_owned(), entry.to_owned())); - } else { - alternatives.push(artifact_name); - } - } - } - - if let Some(entry) = cached_entry { - return Ok(entry); - } - - let mut err = format!("could not find artifact: `{name}`"); - if let Some(suggestion) = super::did_you_mean(name, &alternatives).pop() { - err = format!( - r#"{err} - - Did you mean `{suggestion}`?"# - ); - } - eyre::bail!(err) -} - /// Returns error if constructor has arguments. pub fn ensure_clean_constructor(abi: &JsonAbi) -> Result<()> { if let Some(constructor) = &abi.constructor From 709daa895b3e5f9ba5778be572cbbe098ed3468b Mon Sep 17 00:00:00 2001 From: onbjerg Date: Thu, 8 Jan 2026 10:51:01 +0100 Subject: [PATCH 191/232] chore(cheatcodes): rm dead code (#13016) --- crates/cheatcodes/src/script.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/crates/cheatcodes/src/script.rs b/crates/cheatcodes/src/script.rs index ca9e9e8ccef86..80bd907198a95 100644 --- a/crates/cheatcodes/src/script.rs +++ b/crates/cheatcodes/src/script.rs @@ -320,12 +320,6 @@ impl Wallets { .unwrap_or_else(|| panic!("not all instances were dropped")) } - /// Locks inner Mutex and adds a signer to the [MultiWallet]. - pub fn add_private_key(&self, private_key: &B256) -> Result<()> { - self.add_local_signer(PrivateKeySigner::from_bytes(private_key)?); - Ok(()) - } - /// Locks inner Mutex and adds a signer to the [MultiWallet]. pub fn add_local_signer(&self, wallet: PrivateKeySigner) { self.inner.lock().multi_wallet.add_signer(WalletSigner::Local(wallet)); From 397cc8b8e5a1a1a4b8813f8cb5deb38c0ebcd0da Mon Sep 17 00:00:00 2001 From: onbjerg Date: Thu, 8 Jan 2026 10:52:27 +0100 Subject: [PATCH 192/232] chore(common): rm dead code (#13018) --- crates/common/src/contracts.rs | 9 --------- crates/common/src/serde_helpers.rs | 12 ------------ 2 files changed, 21 deletions(-) diff --git a/crates/common/src/contracts.rs b/crates/common/src/contracts.rs index 5bed2124aee62..f079d0f4fbf3d 100644 --- a/crates/common/src/contracts.rs +++ b/crates/common/src/contracts.rs @@ -395,15 +395,6 @@ impl ContractsByArtifact { Ok(contracts.first().copied()) } - /// Finds abi for contract which has the same contract name or identifier as `id`. - pub fn find_abi_by_name_or_identifier(&self, id: &str) -> Option { - self.iter() - .find(|(artifact, _)| { - artifact.name.split(".").next().unwrap() == id || artifact.identifier() == id - }) - .map(|(_, contract)| contract.abi.clone()) - } - /// Finds abi by name or source path /// /// Returns the abi and the contract name. diff --git a/crates/common/src/serde_helpers.rs b/crates/common/src/serde_helpers.rs index fc04bfbbdb3d5..59c2b7063ca23 100644 --- a/crates/common/src/serde_helpers.rs +++ b/crates/common/src/serde_helpers.rs @@ -37,18 +37,6 @@ impl FromStr for Numeric { } } -/// Deserializes the input into an `Option`, using [`from_int_or_hex`] to deserialize the -/// inner value. -pub fn from_int_or_hex_opt<'de, D>(deserializer: D) -> Result, D::Error> -where - D: Deserializer<'de>, -{ - match Option::::deserialize(deserializer)? { - Some(val) => val.try_into_u256().map(Some), - None => Ok(None), - } -} - /// An enum that represents either a [serde_json::Number] integer, or a hex [U256]. #[derive(Debug, Deserialize)] #[serde(untagged)] From 703ffe40dd2a8f04c3aeaee9b9bb052e43f14117 Mon Sep 17 00:00:00 2001 From: onbjerg Date: Thu, 8 Jan 2026 10:52:36 +0100 Subject: [PATCH 193/232] chore(bench): rm dead code (#13017) --- benches/src/lib.rs | 43 ------------------------------------------- 1 file changed, 43 deletions(-) diff --git a/benches/src/lib.rs b/benches/src/lib.rs index eeb3cbeeafe11..55bbd9762b1d9 100644 --- a/benches/src/lib.rs +++ b/benches/src/lib.rs @@ -6,9 +6,7 @@ use foundry_common::{sh_eprintln, sh_println}; use foundry_compilers::project_util::TempProject; use foundry_test_utils::util::clone_remote; use once_cell::sync::Lazy; -use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; use std::{ - env, path::{Path, PathBuf}, process::Command, str::FromStr, @@ -506,44 +504,3 @@ pub fn get_forge_version_details() -> Result { Ok(lines.first().unwrap_or(&"unknown").to_string()) } } - -/// Get Foundry versions to benchmark from environment variable or default -/// -/// Reads from FOUNDRY_BENCH_VERSIONS environment variable if set, -/// otherwise returns the default versions from FOUNDRY_VERSIONS constant. -/// -/// The environment variable should be a comma-separated list of versions, -/// e.g., "stable,nightly,v1.2.0" -pub fn get_benchmark_versions() -> Vec { - if let Ok(versions_env) = env::var("FOUNDRY_BENCH_VERSIONS") { - versions_env.split(',').map(|s| s.trim().to_string()).filter(|s| !s.is_empty()).collect() - } else { - FOUNDRY_VERSIONS.iter().map(|&s| s.to_string()).collect() - } -} - -/// Setup Repositories for benchmarking -pub fn setup_benchmark_repos() -> Vec<(RepoConfig, BenchmarkProject)> { - // Check for FOUNDRY_BENCH_REPOS environment variable - let repos = if let Ok(repos_env) = env::var("FOUNDRY_BENCH_REPOS") { - // Parse repo specs from the environment variable - // Format should be: "org1/repo1,org2/repo2" - repos_env - .split(',') - .map(|s| s.trim()) - .filter(|s| !s.is_empty()) - .map(|s| s.parse::()) - .collect::>>() - .expect("Failed to parse FOUNDRY_BENCH_REPOS") - } else { - BENCHMARK_REPOS.clone() - }; - - repos - .par_iter() - .map(|repo_config| { - let project = BenchmarkProject::setup(repo_config).expect("Failed to setup project"); - (repo_config.clone(), project) - }) - .collect() -} From 933901d916096150b84eac3b7240304bd8bc3478 Mon Sep 17 00:00:00 2001 From: Theodore Solis Date: Thu, 8 Jan 2026 10:07:36 +0000 Subject: [PATCH 194/232] fix(forge): respect lint ignore config in solar compilation (#12978) Co-authored-by: tefyosL-sol --- crates/cli/src/opts/build/utils.rs | 16 ++++++++++++++-- crates/forge/src/cmd/build.rs | 2 +- crates/forge/src/cmd/lint.rs | 3 ++- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/crates/cli/src/opts/build/utils.rs b/crates/cli/src/opts/build/utils.rs index e204130528946..1952886f36ee0 100644 --- a/crates/cli/src/opts/build/utils.rs +++ b/crates/cli/src/opts/build/utils.rs @@ -91,11 +91,20 @@ pub fn get_solar_sources_from_compile_output( config: &Config, output: &ProjectCompileOutput, target_paths: Option<&[PathBuf]>, + ignored_paths: Option<&[PathBuf]>, ) -> Result { let is_solidity_file = |path: &Path| -> bool { path.extension().and_then(|s| s.to_str()).is_some_and(|ext| SOLC_EXTENSIONS.contains(&ext)) }; + let is_ignored = |path: &Path| -> bool { + if let Some(ignored) = ignored_paths { + ignored.iter().any(|ignored_path| path == ignored_path) + } else { + false + } + }; + // Collect source path targets let mut source_paths: HashSet = if let Some(targets) = target_paths && !targets.is_empty() @@ -111,7 +120,10 @@ pub fn get_solar_sources_from_compile_output( while let Some(path) = queue.pop_front() { if source_paths.insert(path.clone()) { for import in output.graph().imports(path.as_path()) { - queue.push_back(import.to_path_buf()); + // Skip ignored imports to prevent solar from trying to compile them + if !is_ignored(import) { + queue.push_back(import.to_path_buf()); + } } } } @@ -166,7 +178,7 @@ pub fn configure_pcx_from_compile_output( output: &ProjectCompileOutput, target_paths: Option<&[PathBuf]>, ) -> Result<()> { - let solc = get_solar_sources_from_compile_output(config, output, target_paths)?; + let solc = get_solar_sources_from_compile_output(config, output, target_paths, None)?; configure_pcx_from_solc(pcx, &config.project_paths(), &solc, true); Ok(()) } diff --git a/crates/forge/src/cmd/build.rs b/crates/forge/src/cmd/build.rs index d37c73fd68cbb..a98fdc8d7eeb0 100644 --- a/crates/forge/src/cmd/build.rs +++ b/crates/forge/src/cmd/build.rs @@ -175,7 +175,7 @@ impl BuildArgs { .collect::>(); let solar_sources = - get_solar_sources_from_compile_output(config, output, Some(&input_files))?; + get_solar_sources_from_compile_output(config, output, Some(&input_files), None)?; if solar_sources.input.sources.is_empty() { if !input_files.is_empty() { sh_warn!( diff --git a/crates/forge/src/cmd/lint.rs b/crates/forge/src/cmd/lint.rs index c62320b003780..1d5e5857ee594 100644 --- a/crates/forge/src/cmd/lint.rs +++ b/crates/forge/src/cmd/lint.rs @@ -108,7 +108,8 @@ impl LintArgs { .with_mixed_case_exceptions(&config.lint.mixed_case_exceptions); let output = ProjectCompiler::new().files(input.iter().cloned()).compile(&project)?; - let solar_sources = get_solar_sources_from_compile_output(&config, &output, Some(&input))?; + let solar_sources = + get_solar_sources_from_compile_output(&config, &output, Some(&input), Some(&ignored))?; if solar_sources.input.sources.is_empty() { return Err(eyre!( "unable to lint. Solar only supports Solidity versions prior to 0.8.0" From 74d697cb5ef17b5f6a8c68e1531e04065f3bbbeb Mon Sep 17 00:00:00 2001 From: Maxim Evtush <154841002+maximevtush@users.noreply.github.com> Date: Thu, 8 Jan 2026 12:10:43 +0200 Subject: [PATCH 195/232] fix: deduplicate submodule status check logic (#13010) Update mod.rs --- crates/cli/src/utils/mod.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/crates/cli/src/utils/mod.rs b/crates/cli/src/utils/mod.rs index 78e0f87d93e5d..924a717fed3af 100644 --- a/crates/cli/src/utils/mod.rs +++ b/crates/cli/src/utils/mod.rs @@ -699,10 +699,9 @@ ignore them in the `.gitignore` file." /// /// Ref: pub fn submodules_uninitialized(self) -> Result { - self.cmd() - .args(["submodule", "status"]) - .get_stdout_lossy() - .map(|stdout| stdout.lines().any(|line| line.starts_with('-'))) + // keep behavior consistent with `has_missing_dependencies`, but avoid duplicating the + // "submodule status has '-' prefix" logic. + self.has_missing_dependencies(std::iter::empty::<&OsStr>()) } /// Initializes the git submodules. From 04fae2756664825e6d416a94b93132597c08da5a Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Thu, 8 Jan 2026 21:45:22 +0700 Subject: [PATCH 196/232] Foundry/ethereum ux fix tempo #296 (#319) * Potential fix for code scanning alert no. 19: Workflow does not contain permissions Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 61: Workflow does not contain permissions Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 74: Artifact poisoning Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Create config.yml (#105) * Create cargo.yml (#106) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Delete .github/workflows/docker-image.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Rename ci_cargo.yml to cargo.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * fix(fmt): handle trailing coments between base contracts (#12127) * fix(fmt): account for ternary operators when estimating size * fix(fmt): handle comments between inherited base contracts * test: layout + base inheritance * Revert "fix(fmt): handle trailing coments between base contracts (#12127)" This reverts commit b8b5fbb83fa2436063cebc34ddf900abc972b11d. * Update cargo.yml (#172) CI/CD Configuration Update: The CircleCI configuration file, .circleci/cargo.yml, has been updated to use a newer version of the Rust Docker image. Rust Toolchain Version Bump: The cimg/rust Docker image version has been incremented from 1.88.0 to 1.89.0, ensuring builds and tests run with the latest stable Rust toolchain. Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Revert "Create cargo.yml (#106)" This reverts commit 251a2b4fce0c50e3426ffb2022d9abef5b948fa9. * Create cargo.yml (#213) https://github.com/apps/gemini-code-assist Code Review This pull request introduces a CircleCI workflow to automate formatting checks and tests. My review has identified two main issues in the configuration: redundant steps that would unnecessarily increase job execution time, and a mismatch between the Rust version in the CI environment and the one specified in the project's Cargo.toml. I've provided suggestions to fix these issues for a more efficient and consistent CI process. Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Remove duplicate logic in TxSigner::address() implementations * fix(fmt): handle trailing coments between base contracts (#296) @0xrusowsky @Dargon789 fix(fmt): handle trailing coments between base contracts Revert 142 master (#296) * Create ci_cargo.yml (#72) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Create config.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Rename ci_cargo.yml to cargo.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * fix(fmt): handle trailing coments between base contracts (#12127) * fix(fmt): account for ternary operators when estimating size * fix(fmt): handle comments between inherited base contracts * test: layout + base inheritance * Revert "fix(fmt): handle trailing coments between base contracts (#12127)" This reverts commit b8b5fbb83fa2436063cebc34ddf900abc972b11d. * Update cargo.yml (#172) CI/CD Configuration Update: The CircleCI configuration file, .circleci/cargo.yml, has been updated to use a newer version of the Rust Docker image. Rust Toolchain Version Bump: The cimg/rust Docker image version has been incremented from 1.88.0 to 1.89.0, ensuring builds and tests run with the latest stable Rust toolchain. Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Fix cloning of compiler settings for Vyper input Replace context.clone().compiler_settings.vyper with context.compiler_settings.vyper.clone() to avoid unnecessary cloning of the entire VerificationContext. This reduces memory allocations when creating VyperInput instances. Applied to both etherscan and sourcify verification providers. * Remove duplicate logic in TxSigner::address() implementations --------- Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: 0xrusowsky <90208954+0xrusowsky@users.noreply.github.com> Co-authored-by: Gengar Co-authored-by: Aganis --------- Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Co-authored-by: 0xrusowsky <90208954+0xrusowsky@users.noreply.github.com> Co-authored-by: Aganis Co-authored-by: Gengar From aac85e54f87bbf19254a199908d44ab6fd8038cf Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Fri, 16 Jan 2026 10:05:22 +0700 Subject: [PATCH 197/232] Potential fix for code scanning alert no. 94: Uncontrolled data used in path expression Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- crates/test-utils/src/script.rs | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/crates/test-utils/src/script.rs b/crates/test-utils/src/script.rs index 626ce94448a4a..07413fef5495c 100644 --- a/crates/test-utils/src/script.rs +++ b/crates/test-utils/src/script.rs @@ -121,21 +121,32 @@ impl ScriptTester { let to_dir = root.join("utils"); fs::create_dir_all(&to_dir)?; for entry in fs::read_dir(&from_dir)? { - let file = &entry?.path(); - let name = file.file_name().unwrap(); + let file = entry?.path(); + // Only operate on regular files to avoid following symlinks or directories + let metadata = fs::symlink_metadata(&file)?; + let ftype = metadata.file_type(); + if !ftype.is_file() { + continue; + } + let name = match file.file_name() { + Some(name) => name, + None => continue, + }; // Validate file name to avoid path traversal and absolute paths let name_str = name.to_string_lossy(); if name_str.contains("..") || name_str.contains("/") || name_str.contains("\\") { // Skip invalid (potentially dangerous) file names continue; } - // Optionally verify canonicalized file is in from_dir to avoid symlink traversal + // Verify canonicalized file is in from_dir to avoid symlink traversal if let Ok(canonical_file) = file.canonicalize() { if !canonical_file.starts_with(&from_dir) { continue; } + } else { + continue; } - fs::copy(file, to_dir.join(name))?; + fs::copy(&file, to_dir.join(name))?; } Ok(()) } From ecaa54b2f0987d02109f0600785705744bba78e5 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Fri, 16 Jan 2026 10:06:30 +0700 Subject: [PATCH 198/232] Potential fix for code scanning alert no. 104: Uncontrolled data used in path expression Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- npm/scripts/stage-from-artifact.mjs | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/npm/scripts/stage-from-artifact.mjs b/npm/scripts/stage-from-artifact.mjs index c1ca22c8bb2ed..1d39fdc82e84f 100755 --- a/npm/scripts/stage-from-artifact.mjs +++ b/npm/scripts/stage-from-artifact.mjs @@ -64,10 +64,10 @@ function resolveArgs() { strict: true }) - const tool = requireValue(values.tool || process.env.TARGET_TOOL, 'tool') - const platform = requireValue(values.platform || process.env.PLATFORM_NAME, 'platform') - const arch = requireValue(values.arch || process.env.ARCH, 'arch') - const releaseVersion = requireValue( + const tool = requireSafeIdentifier(values.tool || process.env.TARGET_TOOL, 'tool') + const platform = requireSafeIdentifier(values.platform || process.env.PLATFORM_NAME, 'platform') + const arch = requireSafeIdentifier(values.arch || process.env.ARCH, 'arch') + const releaseVersion = requireSafeIdentifier( values.release || values['release-version'] || process.env.RELEASE_VERSION, 'release version' ) @@ -95,6 +95,26 @@ function requireValue(value, name) { throw new Error(`Missing required ${name}`) } +/** + * Ensure a required value is present and consists only of safe identifier + * characters suitable for use in file and directory names. + * + * Allowed characters: letters, digits, dot, underscore, and hyphen. + * + * @param {string | undefined} value + * @param {string} name + * @returns {string} + */ +function requireSafeIdentifier(value, name) { + const trimmed = requireValue(value, name) + if (!/^[A-Za-z0-9._-]+$/.test(trimmed)) { + throw new Error( + `Invalid ${name}: "${trimmed}". Only letters, digits, ".", "_", and "-" are allowed.` + ) + } + return trimmed +} + /** * Determine which archive variant exists for the given artifact prefix. * @param {string} prefix From e5f8f49f4a400837c6f888369d86ecc3daedd812 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Fri, 16 Jan 2026 10:07:08 +0700 Subject: [PATCH 199/232] Potential fix for code scanning alert no. 105: Server-side request forgery Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- npm/src/const.mjs | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/npm/src/const.mjs b/npm/src/const.mjs index a37e8dfd7ae30..d07978918c4eb 100644 --- a/npm/src/const.mjs +++ b/npm/src/const.mjs @@ -1,4 +1,5 @@ import * as NodePath from 'node:path' +import { URL } from 'node:url' /** * @typedef {'amd64' | 'arm64'} Arch @@ -33,11 +34,36 @@ export function resolveTargetTool(raw = process.env.TARGET_TOOL || process.argv[ export function getRegistryUrl() { // Prefer npm's configured registry (works with Verdaccio and custom registries) // Fallback to REGISTRY_URL for tests/dev, then npmjs - return ( + const raw = process.env.npm_config_registry || process.env.REGISTRY_URL || 'https://registry.npmjs.org' - ) + + let parsed + try { + parsed = new URL(raw) + } catch { + throw new Error(`Invalid registry URL: "${raw}"`) + } + + // Enforce secure scheme + if (parsed.protocol !== 'https:') { + throw new Error(`Insecure registry URL scheme "${parsed.protocol}". Only "https:" is allowed.`) + } + + // Basic SSRF mitigation: disallow obvious loopback hosts + const hostname = parsed.hostname.toLowerCase() + if ( + hostname === 'localhost' + || hostname === '127.0.0.1' + || hostname === '::1' + ) { + throw new Error(`Registry URL host "${parsed.hostname}" is not allowed.`) + } + + // Normalize to a consistent base URL without trailing slash + const base = parsed.origin + parsed.pathname + return base.replace(/\/+$/, '') } /** From 04b8cfd9640a40b1d8e921481c4bf969ad418ab3 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Fri, 16 Jan 2026 10:17:39 +0700 Subject: [PATCH 200/232] fix: add Tempo transaction receipt type support in TryFrom conversion (#334) * fix: add Tempo transaction receipt type support in TryFrom conversion (#13047) Amp-Thread-ID: https://ampcode.com/threads/T-019bbf45-d7c8-75ed-8c05-bc1638d487ee Co-authored-by: Matthias Seitz Co-authored-by: Amp * feat(cheatcodes): add getRecordedLogsJson cheatcode (#13093) Adds a new cheatcode `getRecordedLogsJson` that returns recorded logs as a JSON string, similar to the existing `getStateDiffJson` pattern. This allows users to easily post-process recorded logs externally without needing to manually transform the Log[] array to JSON. JSON format: ```json [{"topics": ["0x..."], "data": "0x...", "emitter": "0x..."}] ``` Closes #12854 * feat: add Sourcify support to forge clone (#12900) * Integrate Sourcify API for contract cloning Added support for Sourcify API in `forge clone` command. * Add reqwest dependency with json feature * Remove unused import in clone.rs Removed unused import of BTreeMap. * Refactor EtherscanClient to ExplorerClient * Change sourcify module from private to public * Implement test for sourcify clone functionality Add test for cloning with sourcify source * Update clone.rs * Add url dependency to Cargo.toml * cargo fmt * Enhance Sourcify client with cached creation data Updated the Sourcify client to cache creation data and reuse it across API calls, improving efficiency. Modified the contract source code retrieval to include additional creation data fields. * Improve error handling for contract data retrieval Refactor contract source code and creation data retrieval to use fallback values when API requests fail or fields are unavailable. * Enhance contract_source_code with improved caching Updated contract_source_code to include additional fields in the API request and improved caching of creation data. Removed fallback logic for fetching creation data from the API. * Refactor creation_data handling in clone.rs Removed redundant creation_data initialization and caching. * Refactor response deserialization to use untagged enum * fix: use serde_json::Value for abi in Sourcify parsing The #[serde(untagged)] enum SourcifyContractResponse failed to deserialize because Box doesn't work with untagged enums. RawValue requires borrowing from the original JSON, but untagged enums buffer data during variant matching. Changes: - Change abi field from Box to serde_json::Value - Truncate response in error messages to avoid huge output * feat: add --sourcify-url option for custom Sourcify API endpoint * feat: imply --source sourcify when --sourcify-url is specified * feat: support full path in --sourcify-url When --sourcify-url contains v2/contract/chain, only append address and fields instead of building the full path again. --------- Co-authored-by: grandizzy * perf: add dist profile for smaller release binaries (#13097) * perf: add dist profile for smaller release binaries Add a new 'dist' Cargo profile optimized for distribution: - Fat LTO and codegen-units=1 for better optimization - Strip symbols for smaller binaries - opt-level="s" overrides for non-perf-critical dependencies Benchmarks on Solady test suite show dist is 8% faster than release while being 45% smaller (43MB vs 78MB). Update release workflows to use the dist profile instead of maxperf. * Apply suggestion from @DaniPopes --------- Co-authored-by: DaniPopes <57450786+DaniPopes@users.noreply.github.com> * chore(deps): update figment to figment2 v0.11 (#13099) * chore(deps): update figment to figment2 v0.11 * rename * feat: add precompile decoding for Prague BLS12-381 and Osaka P256VERIFY (#13094) * feat: add precompile decoding for Prague BLS12-381 and Osaka P256VERIFY * wip * wip * fix(traces): use raw byte decoding for P256VERIFY precompile P256VERIFY (RIP-7212) uses concatenated raw bytes, not ABI encoding: - Input: hash (32) + r (32) + s (32) + qx (32) + qy (32) = 160 bytes - Output: 32 bytes where 0x...01 means success * fix(traces): use raw byte decoding for all precompiles Precompiles use concatenated raw bytes, not ABI encoding: - ecrecover: hash (32) + v (32) + r (32) + s (32), returns address in last 20 bytes - sha256/ripemd160: raw input, raw 32-byte output (ripemd in last 20 bytes) - ecadd: x1/y1/x2/y2 (32 each), returns x/y (32 each) - ecmul: x1/y1/s (32 each), returns x/y (32 each) - ecpairing: returns 32-byte bool (1 = success) - bls12PairingCheck: returns 32-byte bool (1 = success) * fix(traces): restore ABI-based precompile decoding * fix * fix(anvil): use suggested priority fee by default (#13092) * fix(anvil): use suggested priority fee by default * test: fix anvil trace expectations --------- Co-authored-by: tefyosL-sol * chore: aggregate PRs (#13100) * chore: aggregate PRs This PR aggregates changes from the following PRs: - Closes #13032 by @\splinter012 - Closes #13059 by @\phrwlk * fmt * chore(evm): misleading error message in traces serialization (#13081) Co-authored-by: tefyosL-sol --------- Co-authored-by: Desant pivo Co-authored-by: Matthias Seitz Co-authored-by: Amp Co-authored-by: grandizzy <38490174+grandizzy@users.noreply.github.com> Co-authored-by: Avory Co-authored-by: grandizzy Co-authored-by: onbjerg Co-authored-by: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Co-authored-by: Theodore Solis Co-authored-by: tefyosL-sol --- .github/workflows/docker-publish.yml | 2 +- .github/workflows/release.yml | 2 +- Cargo.lock | 148 ++----- Cargo.toml | 72 ++- crates/anvil/src/eth/api.rs | 3 +- crates/anvil/tests/it/traces.rs | 2 +- crates/cast/tests/cli/main.rs | 2 +- crates/cheatcodes/assets/cheatcodes.json | 20 + crates/cheatcodes/spec/src/vm.rs | 4 + crates/cheatcodes/src/evm.rs | 28 ++ crates/config/src/error.rs | 4 +- crates/evm/core/src/precompiles.rs | 32 ++ crates/evm/evm/src/inspectors/stack.rs | 8 +- crates/evm/traces/src/decoder/mod.rs | 13 +- crates/evm/traces/src/decoder/precompiles.rs | 183 +++++++- crates/evm/traces/src/lib.rs | 2 +- crates/fmt/src/state/mod.rs | 9 - crates/fmt/src/state/sol.rs | 11 - crates/forge/Cargo.toml | 2 + crates/forge/src/cmd/clone.rs | 435 +++++++++++++++++-- crates/forge/tests/cli/cmd.rs | 27 ++ crates/forge/tests/cli/precompiles.rs | 172 ++++++++ crates/primitives/src/network/receipt.rs | 2 + crates/verify/src/lib.rs | 2 +- npm/env.d.ts | 4 +- npm/src/const.mjs | 2 +- testdata/default/cheats/RecordLogs.t.sol | 35 ++ testdata/utils/Vm.sol | 1 + 28 files changed, 1022 insertions(+), 205 deletions(-) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 369875f9373b3..614aa6a508f67 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -24,7 +24,7 @@ env: IMAGE_NAME: ${{ github.repository }} # Keep in sync with `release.yml`. - RUST_PROFILE: maxperf + RUST_PROFILE: dist RUST_FEATURES: aws-kms,gcp-kms,turnkey,cli,asm-keccak,js-tracer jobs: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5049cd617a0c1..85cc3e6f5859d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,7 +18,7 @@ env: IS_NIGHTLY: ${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' }} # Keep in sync with `docker-publish.yml`. - RUST_PROFILE: maxperf + RUST_PROFILE: dist RUST_FEATURES: aws-kms,gcp-kms,turnkey,cli,asm-keccak,js-tracer LAST_STABLE_VERSION: "v1.5.0" diff --git a/Cargo.lock b/Cargo.lock index ba6c0b99014d2..a27d890bc918a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1065,7 +1065,7 @@ version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -1089,7 +1089,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -3606,7 +3606,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -3902,7 +3902,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -4096,17 +4096,16 @@ dependencies = [ ] [[package]] -name = "figment" -version = "0.10.19" +name = "figment2" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cb01cd46b0cf372153850f4c6c272d9cbea2da513e07538405148f95bd789f3" +checksum = "4380ce44915a6227efbb61e3885bc1c8e99fb9820f5db612abfac2c5cfc46871" dependencies = [ "atomic", "parking_lot", - "pear", "serde", "tempfile", - "toml 0.8.23", + "toml_edit 0.23.10+spec-1.0.0", "uncased", "version_check", ] @@ -4247,6 +4246,7 @@ dependencies = [ "toml_edit 0.24.0+spec-1.1.0", "tower-http", "tracing", + "url", "watchexec", "watchexec-events", "watchexec-signals", @@ -4273,7 +4273,7 @@ dependencies = [ "serde_json", "solar-compiler", "thiserror 2.0.17", - "toml 0.9.11+spec-1.1.0", + "toml", "tracing", ] @@ -4288,7 +4288,7 @@ dependencies = [ "similar", "snapbox", "solar-compiler", - "toml 0.9.11+spec-1.1.0", + "toml", ] [[package]] @@ -4507,7 +4507,7 @@ dependencies = [ "serde_json", "solar-compiler", "thiserror 2.0.17", - "toml 0.9.11+spec-1.1.0", + "toml", "tracing", "walkdir", ] @@ -4759,7 +4759,7 @@ dependencies = [ "dirs", "dunce", "eyre", - "figment", + "figment2", "foundry-block-explorers", "foundry-compilers", "foundry-evm-networks", @@ -4782,7 +4782,7 @@ dependencies = [ "soldeer-core", "tempfile", "thiserror 2.0.17", - "toml 0.9.11+spec-1.1.0", + "toml", "toml_edit 0.24.0+spec-1.1.0", "tracing", "unit-prefix", @@ -5341,7 +5341,7 @@ dependencies = [ "libc", "log", "rustversion", - "windows-link 0.1.3", + "windows-link 0.2.1", "windows-result 0.4.1", ] @@ -5998,12 +5998,6 @@ dependencies = [ "str_stack", ] -[[package]] -name = "inlinable_string" -version = "0.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb" - [[package]] name = "inotify" version = "0.11.0" @@ -6107,7 +6101,7 @@ checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" dependencies = [ "hermit-abi", "libc", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -6537,7 +6531,7 @@ dependencies = [ "regex", "serde", "serde_json", - "toml 0.9.11+spec-1.1.0", + "toml", "tracing", ] @@ -6560,7 +6554,7 @@ dependencies = [ "serde_json", "shlex", "tempfile", - "toml 0.9.11+spec-1.1.0", + "toml", "topological-sort", "tracing", ] @@ -6924,7 +6918,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -7406,29 +7400,6 @@ dependencies = [ "hmac", ] -[[package]] -name = "pear" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdeeaa00ce488657faba8ebf44ab9361f9365a97bd39ffb8a60663f57ff4b467" -dependencies = [ - "inlinable_string", - "pear_codegen", - "yansi", -] - -[[package]] -name = "pear_codegen" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bab5b985dc082b345f812b7df84e1bef27e7207b39e448439ba8bd69c93f147" -dependencies = [ - "proc-macro2", - "proc-macro2-diagnostics", - "quote", - "syn 2.0.114", -] - [[package]] name = "pem" version = "3.0.6" @@ -7841,19 +7812,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "proc-macro2-diagnostics" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.114", - "version_check", - "yansi", -] - [[package]] name = "process-wrap" version = "8.2.1" @@ -8959,7 +8917,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -9377,15 +9335,6 @@ dependencies = [ "serde_core", ] -[[package]] -name = "serde_spanned" -version = "0.6.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" -dependencies = [ - "serde", -] - [[package]] name = "serde_spanned" version = "1.0.4" @@ -10196,7 +10145,7 @@ dependencies = [ "getrandom 0.3.4", "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -10236,7 +10185,7 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8c27177b12a6399ffc08b98f76f7c9a1f4fe9fc967c784c5a071fa8d93cf7e1" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -10522,18 +10471,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "toml" -version = "0.8.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" -dependencies = [ - "serde", - "serde_spanned 0.6.9", - "toml_datetime 0.6.11", - "toml_edit 0.22.27", -] - [[package]] name = "toml" version = "0.9.11+spec-1.1.0" @@ -10542,22 +10479,13 @@ checksum = "f3afc9a848309fe1aaffaed6e1546a7a14de1f935dc9d89d32afd9a44bab7c46" dependencies = [ "indexmap 2.13.0", "serde_core", - "serde_spanned 1.0.4", - "toml_datetime 0.7.5+spec-1.1.0", + "serde_spanned", + "toml_datetime", "toml_parser", "toml_writer", "winnow", ] -[[package]] -name = "toml_datetime" -version = "0.6.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" -dependencies = [ - "serde", -] - [[package]] name = "toml_datetime" version = "0.7.5+spec-1.1.0" @@ -10567,20 +10495,6 @@ dependencies = [ "serde_core", ] -[[package]] -name = "toml_edit" -version = "0.22.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" -dependencies = [ - "indexmap 2.13.0", - "serde", - "serde_spanned 0.6.9", - "toml_datetime 0.6.11", - "toml_write", - "winnow", -] - [[package]] name = "toml_edit" version = "0.23.10+spec-1.0.0" @@ -10589,8 +10503,8 @@ checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269" dependencies = [ "indexmap 2.13.0", "serde_core", - "serde_spanned 1.0.4", - "toml_datetime 0.7.5+spec-1.1.0", + "serde_spanned", + "toml_datetime", "toml_parser", "toml_writer", "winnow", @@ -10603,7 +10517,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c740b185920170a6d9191122cafef7010bd6270a3824594bff6784c04d7f09e" dependencies = [ "indexmap 2.13.0", - "toml_datetime 0.7.5+spec-1.1.0", + "toml_datetime", "toml_parser", "toml_writer", "winnow", @@ -10618,12 +10532,6 @@ dependencies = [ "winnow", ] -[[package]] -name = "toml_write" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" - [[package]] name = "toml_writer" version = "1.0.6+spec-1.1.0" @@ -11539,7 +11447,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 0c43b235223fa..6da5c1359a06c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -92,7 +92,7 @@ strip = "none" [profile.bench] inherits = "profiling" -[profile.maxperf] +[profile.dist] inherits = "release" lto = "fat" codegen-units = 1 @@ -182,18 +182,62 @@ walkdir.opt-level = 3 # Override packages which aren't perf-sensitive for faster compilation speed and smaller binary size. [profile.release.package] -alloy-sol-macro-expander.opt-level = "z" -figment.opt-level = "z" -foundry-compilers-artifacts-solc.opt-level = "z" -foundry-config.opt-level = "z" -html5ever.opt-level = "z" -mdbook-driver.opt-level = "z" -prettyplease.opt-level = "z" -protobuf.opt-level = "z" -pulldown-cmark.opt-level = "z" -syn-solidity.opt-level = "z" -syn.opt-level = "z" -trezor-client.opt-level = "z" +alloy-sol-macro-expander.opt-level = "s" +figment2.opt-level = "s" +foundry-compilers-artifacts-solc.opt-level = "s" +foundry-config.opt-level = "s" +html5ever.opt-level = "s" +mdbook-driver.opt-level = "s" +prettyplease.opt-level = "s" +protobuf.opt-level = "s" +pulldown-cmark.opt-level = "s" +syn-solidity.opt-level = "s" +syn.opt-level = "s" +trezor-client.opt-level = "s" + +# Networking stack (not perf-critical for CLI tools). +reqwest.opt-level = "s" +hyper.opt-level = "s" +hyper-util.opt-level = "s" +h2.opt-level = "s" +rustls.opt-level = "s" +tower.opt-level = "s" +tower-http.opt-level = "s" + +# Doc generation / templating. +mdbook-core.opt-level = "s" +mdbook-html.opt-level = "s" +font-awesome-as-a-crate.opt-level = "s" +handlebars.opt-level = "s" + +# Watch mode. +watchexec.opt-level = "s" +watchexec-events.opt-level = "s" +watchexec-signals.opt-level = "s" +watchexec-supervisor.opt-level = "s" + +# Soldeer package manager. +soldeer-commands.opt-level = "s" +soldeer-core.opt-level = "s" + +# Parsing / editing (not perf-sensitive in CLI). +toml_edit.opt-level = "s" +toml.opt-level = "s" + +# Block explorers / verification. +foundry-block-explorers.opt-level = "s" + +# Misc CLI dependencies. +clap_builder.opt-level = "s" +clap_complete.opt-level = "s" +comfy-table.opt-level = "s" +indicatif.opt-level = "s" +dialoguer.opt-level = "s" +ratatui.opt-level = "s" +crossterm.opt-level = "s" + +# Alloy JSON (parsing, not hot path). +alloy-json-abi.opt-level = "s" [workspace.dependencies] anvil = { path = "crates/anvil" } @@ -342,7 +386,7 @@ dunce = "1" evm-disassembler = "0.6" evmole = "0.8" eyre = "0.6" -figment = "0.10" +figment = { package = "figment2", version = "0.11" } futures = { version = "0.3", default-features = false } hyper = "1.8" indicatif = "0.18" diff --git a/crates/anvil/src/eth/api.rs b/crates/anvil/src/eth/api.rs index 53db1bc9670c4..3e783b7dbafaa 100644 --- a/crates/anvil/src/eth/api.rs +++ b/crates/anvil/src/eth/api.rs @@ -3354,11 +3354,10 @@ impl EthApi { .max_fee_per_gas() .is_none() .then(|| request.set_max_fee_per_gas(self.gas_price())); - // TODO: use suggested tip instead of 0 request .max_priority_fee_per_gas() .is_none() - .then(|| request.set_max_priority_fee_per_gas(Default::default())); + .then(|| request.set_max_priority_fee_per_gas(MIN_SUGGESTED_PRIORITY_FEE)); } if tx_type == FoundryTxType::Eip4844 { request.as_ref().max_fee_per_blob_gas().is_none().then(|| { diff --git a/crates/anvil/tests/it/traces.rs b/crates/anvil/tests/it/traces.rs index dd4a196831cea..5bf7e1afb5457 100644 --- a/crates/anvil/tests/it/traces.rs +++ b/crates/anvil/tests/it/traces.rs @@ -1237,7 +1237,7 @@ async fn test_debug_trace_transaction_pre_state_tracer() { let expected = r#" { "0x0000000000000000000000000000000000000000": { - "balance": "0x0" + "balance": "1206031000000000" }, "0x5fbdb2315678afecb367f032d93f642f64180aa3": { "balance": "0x0", diff --git a/crates/cast/tests/cli/main.rs b/crates/cast/tests/cli/main.rs index c4a809f6c065c..5946d87986190 100644 --- a/crates/cast/tests/cli/main.rs +++ b/crates/cast/tests/cli/main.rs @@ -3749,7 +3749,7 @@ Traces: │ │ │ │ └─ ← [Return] 0xc13089327d3c20c0ce35f2f058c423de29977e6950e406c095e366a8fabd463f │ │ │ ├─ [96] PRECOMPILES::sha256(0x424242424242424242424242424242424242424242424242424242424242424201000000c13089327d3c20c0ce35f2f058c423de29977e6950e406c095e366a8fabd463f) [staticcall] │ │ │ │ └─ ← [Return] 0xc544bd9a4ea526dda3a008f43c21b6f0be3031b1ff71832b9876915dc91deea0 - │ │ │ ├─ [6900] 0x0000000000000000000000000000000000000100::c544bd9a(4ea526dda3a008f43c21b6f0be3031b1ff71832b9876915dc91deea0dd519280ec730727f07aa36550bde31a1d5f3097818f3425c2f083ed33a91f080fa2afac0071f6e1af9a0e9c09b851bf01e68bc8a1c1f89f686c48205762f925bf54fa13f88658092efa36c51b1e3c4db31d3afb92812fb852dac7cf9614bc479bf5da7241d9c4ab1b431b57ec3369587b4c831d7a564438990da053708c3289) [staticcall] + │ │ │ ├─ [6900] P256VERIFY::c544bd9a(4ea526dda3a008f43c21b6f0be3031b1ff71832b9876915dc91deea0dd519280ec730727f07aa36550bde31a1d5f3097818f3425c2f083ed33a91f080fa2afac0071f6e1af9a0e9c09b851bf01e68bc8a1c1f89f686c48205762f925bf54fa13f88658092efa36c51b1e3c4db31d3afb92812fb852dac7cf9614bc479bf5da7241d9c4ab1b431b57ec3369587b4c831d7a564438990da053708c3289) [staticcall] │ │ │ │ └─ ← [Return] 0x0000000000000000000000000000000000000000000000000000000000000001 │ │ │ └─ ← [Return] 0x00000000000000000000000000000000000000000000000000000000000000011bde17b8de18819c9eb86cefc3920ddb5d3d4254de276e3d6e18dd2b399f732b │ │ └─ ← [Return] 0x00000000000000000000000000000000000000000000000000000000000000011bde17b8de18819c9eb86cefc3920ddb5d3d4254de276e3d6e18dd2b399f732b diff --git a/crates/cheatcodes/assets/cheatcodes.json b/crates/cheatcodes/assets/cheatcodes.json index 2134b95ac571d..67820b2030c23 100644 --- a/crates/cheatcodes/assets/cheatcodes.json +++ b/crates/cheatcodes/assets/cheatcodes.json @@ -6524,6 +6524,26 @@ "status": "stable", "safety": "safe" }, + { + "func": { + "id": "getRecordedLogsJson", + "description": "Gets all the recorded logs, in JSON format.", + "declaration": "function getRecordedLogsJson() external view returns (string memory logsJson);", + "visibility": "external", + "mutability": "view", + "signature": "getRecordedLogsJson()", + "selector": "0x3b171111", + "selectorBytes": [ + 59, + 23, + 17, + 17 + ] + }, + "group": "evm", + "status": "stable", + "safety": "safe" + }, { "func": { "id": "getStateDiff", diff --git a/crates/cheatcodes/spec/src/vm.rs b/crates/cheatcodes/spec/src/vm.rs index 59b6d96eec2f1..640c97e3108fb 100644 --- a/crates/cheatcodes/spec/src/vm.rs +++ b/crates/cheatcodes/spec/src/vm.rs @@ -951,6 +951,10 @@ interface Vm { #[cheatcode(group = Evm, safety = Safe)] function getRecordedLogs() external view returns (Log[] memory logs); + /// Gets all the recorded logs, in JSON format. + #[cheatcode(group = Evm, safety = Safe)] + function getRecordedLogsJson() external view returns (string memory logsJson); + // -------- Gas Metering -------- // It's recommend to use the `noGasMetering` modifier included with forge-std, instead of diff --git a/crates/cheatcodes/src/evm.rs b/crates/cheatcodes/src/evm.rs index 70e5f66785999..b5e76e1148694 100644 --- a/crates/cheatcodes/src/evm.rs +++ b/crates/cheatcodes/src/evm.rs @@ -55,6 +55,18 @@ pub(crate) mod mapping; pub(crate) mod mock; pub(crate) mod prank; +/// JSON-serializable log entry for `getRecordedLogsJson`. +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +struct LogJson { + /// The topics of the log, including the signature, if any. + topics: Vec, + /// The raw data of the log, hex-encoded with 0x prefix. + data: String, + /// The address of the log's emitter. + emitter: String, +} + /// Records storage slots reads and writes. #[derive(Clone, Debug, Default)] pub struct RecordAccess { @@ -403,6 +415,22 @@ impl Cheatcode for getRecordedLogsCall { } } +impl Cheatcode for getRecordedLogsJsonCall { + fn apply(&self, state: &mut Cheatcodes) -> Result { + let Self {} = self; + let logs = state.recorded_logs.replace(Default::default()).unwrap_or_default(); + let json_logs: Vec<_> = logs + .into_iter() + .map(|log| LogJson { + topics: log.topics.iter().map(|t| format!("{t}")).collect(), + data: hex::encode_prefixed(&log.data), + emitter: format!("{}", log.emitter), + }) + .collect(); + Ok(serde_json::to_string(&json_logs)?.abi_encode()) + } +} + impl Cheatcode for pauseGasMeteringCall { fn apply(&self, state: &mut Cheatcodes) -> Result { let Self {} = self; diff --git a/crates/config/src/error.rs b/crates/config/src/error.rs index 61d954ef73956..67cc8d7e04762 100644 --- a/crates/config/src/error.rs +++ b/crates/config/src/error.rs @@ -12,7 +12,7 @@ pub struct ExtractConfigError { } impl ExtractConfigError { - /// Wraps the figment error + /// Wraps the figment error. pub fn new(error: figment::Error) -> Self { Self { error } } @@ -63,7 +63,7 @@ impl Error for ExtractConfigError { pub enum FoundryConfigError { /// An error thrown during toml parsing Toml(figment::Error), - /// Any other error thrown when constructing the config's figment + /// Any other error thrown when constructing the config's figment. Other(figment::Error), } diff --git a/crates/evm/core/src/precompiles.rs b/crates/evm/core/src/precompiles.rs index 62f7397a12bf9..fd569dc30dc07 100644 --- a/crates/evm/core/src/precompiles.rs +++ b/crates/evm/core/src/precompiles.rs @@ -30,6 +30,30 @@ pub const BLAKE_2F: Address = address!("0x00000000000000000000000000000000000000 /// The PointEvaluation precompile address. pub const POINT_EVALUATION: Address = address!("0x000000000000000000000000000000000000000a"); +/// The BLS12-381 G1ADD precompile address. +pub const BLS12_G1ADD: Address = address!("0x000000000000000000000000000000000000000b"); + +/// The BLS12-381 G1MSM precompile address. +pub const BLS12_G1MSM: Address = address!("0x000000000000000000000000000000000000000c"); + +/// The BLS12-381 G2ADD precompile address. +pub const BLS12_G2ADD: Address = address!("0x000000000000000000000000000000000000000d"); + +/// The BLS12-381 G2MSM precompile address. +pub const BLS12_G2MSM: Address = address!("0x000000000000000000000000000000000000000e"); + +/// The BLS12-381 pairing check precompile address. +pub const BLS12_PAIRING_CHECK: Address = address!("0x000000000000000000000000000000000000000f"); + +/// The BLS12-381 map Fp to G1 precompile address. +pub const BLS12_MAP_FP_TO_G1: Address = address!("0x0000000000000000000000000000000000000010"); + +/// The BLS12-381 map Fp2 to G2 precompile address. +pub const BLS12_MAP_FP2_TO_G2: Address = address!("0x0000000000000000000000000000000000000011"); + +/// The P256VERIFY precompile address. +pub const P256_VERIFY: Address = address!("0x0000000000000000000000000000000000000100"); + /// Precompile addresses. pub const PRECOMPILES: &[Address] = &[ EC_RECOVER, @@ -42,4 +66,12 @@ pub const PRECOMPILES: &[Address] = &[ EC_PAIRING, BLAKE_2F, POINT_EVALUATION, + BLS12_G1ADD, + BLS12_G1MSM, + BLS12_G2ADD, + BLS12_G2MSM, + BLS12_PAIRING_CHECK, + BLS12_MAP_FP_TO_G1, + BLS12_MAP_FP2_TO_G2, + P256_VERIFY, ]; diff --git a/crates/evm/evm/src/inspectors/stack.rs b/crates/evm/evm/src/inspectors/stack.rs index 8d889eca9a329..a76409308a0b3 100644 --- a/crates/evm/evm/src/inspectors/stack.rs +++ b/crates/evm/evm/src/inspectors/stack.rs @@ -964,11 +964,13 @@ impl Inspector> for InspectorStackRefMut<'_> if let Some(cheatcodes) = self.cheatcodes.as_deref_mut() { // Handle mocked functions, replace bytecode address with mock if matched. if let Some(mocks) = cheatcodes.mocked_functions.get(&call.target_address) { + let input_bytes = call.input.bytes(ecx); // Check if any mock function set for call data or if catch-all mock function set // for selector. - if let Some(target) = mocks.get(&call.input.bytes(ecx)).or_else(|| { - call.input.bytes(ecx).get(..4).and_then(|selector| mocks.get(selector)) - }) { + if let Some(target) = mocks + .get(&input_bytes) + .or_else(|| input_bytes.get(..4).and_then(|selector| mocks.get(selector))) + { call.bytecode_address = *target; call.known_bytecode = None; } diff --git a/crates/evm/traces/src/decoder/mod.rs b/crates/evm/traces/src/decoder/mod.rs index 4f377fe03c510..38f40b244c042 100644 --- a/crates/evm/traces/src/decoder/mod.rs +++ b/crates/evm/traces/src/decoder/mod.rs @@ -18,8 +18,9 @@ use foundry_evm_core::{ constants::{CALLER, CHEATCODE_ADDRESS, DEFAULT_CREATE2_DEPLOYER, HARDHAT_CONSOLE_ADDRESS}, decode::RevertDecoder, precompiles::{ - BLAKE_2F, EC_ADD, EC_MUL, EC_PAIRING, EC_RECOVER, IDENTITY, MOD_EXP, POINT_EVALUATION, - RIPEMD_160, SHA_256, + BLAKE_2F, BLS12_G1ADD, BLS12_G1MSM, BLS12_G2ADD, BLS12_G2MSM, BLS12_MAP_FP_TO_G1, + BLS12_MAP_FP2_TO_G2, BLS12_PAIRING_CHECK, EC_ADD, EC_MUL, EC_PAIRING, EC_RECOVER, IDENTITY, + MOD_EXP, P256_VERIFY, POINT_EVALUATION, RIPEMD_160, SHA_256, }, }; use itertools::Itertools; @@ -183,6 +184,14 @@ impl CallTraceDecoder { (EC_PAIRING, "ECPairing".to_string()), (BLAKE_2F, "Blake2F".to_string()), (POINT_EVALUATION, "PointEvaluation".to_string()), + (BLS12_G1ADD, "BLS12_G1ADD".to_string()), + (BLS12_G1MSM, "BLS12_G1MSM".to_string()), + (BLS12_G2ADD, "BLS12_G2ADD".to_string()), + (BLS12_G2MSM, "BLS12_G2MSM".to_string()), + (BLS12_PAIRING_CHECK, "BLS12_PAIRING_CHECK".to_string()), + (BLS12_MAP_FP_TO_G1, "BLS12_MAP_FP_TO_G1".to_string()), + (BLS12_MAP_FP2_TO_G2, "BLS12_MAP_FP2_TO_G2".to_string()), + (P256_VERIFY, "P256VERIFY".to_string()), ]), receive_contracts: Default::default(), fallback_contracts: Default::default(), diff --git a/crates/evm/traces/src/decoder/precompiles.rs b/crates/evm/traces/src/decoder/precompiles.rs index 7437c4eb1a3a1..fdbe744641cd7 100644 --- a/crates/evm/traces/src/decoder/precompiles.rs +++ b/crates/evm/traces/src/decoder/precompiles.rs @@ -2,8 +2,9 @@ use crate::{CallTrace, DecodedCallData}; use alloy_primitives::{Address, B256, U256, hex}; use alloy_sol_types::{SolCall, abi, sol}; use foundry_evm_core::precompiles::{ - BLAKE_2F, EC_ADD, EC_MUL, EC_PAIRING, EC_RECOVER, IDENTITY, MOD_EXP, POINT_EVALUATION, - RIPEMD_160, SHA_256, + BLAKE_2F, BLS12_G1ADD, BLS12_G1MSM, BLS12_G2ADD, BLS12_G2MSM, BLS12_MAP_FP_TO_G1, + BLS12_MAP_FP2_TO_G2, BLS12_PAIRING_CHECK, EC_ADD, EC_MUL, EC_PAIRING, EC_RECOVER, IDENTITY, + MOD_EXP, P256_VERIFY, POINT_EVALUATION, RIPEMD_160, SHA_256, }; use itertools::Itertools; use revm_inspectors::tracing::types::DecodedCallTrace; @@ -33,6 +34,18 @@ interface Precompiles { /* 0x08 */ function ecpairing(EcPairingInput[] input) returns (bool success); /* 0x09 */ function blake2f(uint32 rounds, uint64[8] h, uint64[16] m, uint64[2] t, bool f) returns (uint64[8] h); /* 0x0a */ function pointEvaluation(bytes32 versionedHash, bytes32 z, bytes32 y, bytes1[48] commitment, bytes1[48] proof) returns (bytes value); + + // Prague BLS12-381 precompiles (EIP-2537) + /* 0x0b */ function bls12G1Add(bytes p1, bytes p2) returns (bytes result); + /* 0x0c */ function bls12G1Msm(bytes[] scalarsAndPoints) returns (bytes result); + /* 0x0d */ function bls12G2Add(bytes p1, bytes p2) returns (bytes result); + /* 0x0e */ function bls12G2Msm(bytes[] scalarsAndPoints) returns (bytes result); + /* 0x0f */ function bls12PairingCheck(bytes[] pairs) returns (bool success); + /* 0x10 */ function bls12MapFpToG1(bytes fp) returns (bytes result); + /* 0x11 */ function bls12MapFp2ToG2(bytes fp2) returns (bytes result); + + // Osaka precompiles (EIP-7212) + /* 0x100 */ function p256Verify(bytes32 hash, uint256 r, uint256 s, uint256 qx, uint256 qy) returns (bool success); } } use Precompiles::*; @@ -51,6 +64,14 @@ pub(super) fn is_known_precompile(address: Address, _chain_id: u64) -> bool { | EC_PAIRING | BLAKE_2F | POINT_EVALUATION + | BLS12_G1ADD + | BLS12_G1MSM + | BLS12_G2ADD + | BLS12_G2MSM + | BLS12_PAIRING_CHECK + | BLS12_MAP_FP_TO_G1 + | BLS12_MAP_FP2_TO_G2 + | P256_VERIFY ) } @@ -115,6 +136,14 @@ const PRECOMPILES: &[&dyn Precompile] = &[ &Ecpairing, &Blake2f, &PointEvaluation, + &Bls12G1Add, + &Bls12G1Msm, + &Bls12G2Add, + &Bls12G2Msm, + &Bls12PairingCheck, + &Bls12MapFpToG1, + &Bls12MapFp2ToG2, + &P256Verify, ]; struct Ecrecover; @@ -346,6 +375,156 @@ fn iter_to_string, T: std::fmt::Display>(iter: I) -> Strin format!("[{}]", iter.format(", ")) } +const G1_POINT_SIZE: usize = 128; +const G2_POINT_SIZE: usize = 256; +const SCALAR_SIZE: usize = 32; +const FP_SIZE: usize = 64; + +struct Bls12G1Add; +impl Precompile for Bls12G1Add { + fn address(&self) -> Address { + BLS12_G1ADD + } + + fn signature(&self, _: &[u8]) -> &'static str { + bls12G1AddCall::SIGNATURE + } + + fn decode_call(&self, data: &[u8]) -> alloy_sol_types::Result> { + let (p1, rest) = take_at_most(data, G1_POINT_SIZE); + let (p2, _) = take_at_most(rest, G1_POINT_SIZE); + Ok(vec![hex::encode_prefixed(p1), hex::encode_prefixed(p2)]) + } +} + +struct Bls12G1Msm; +impl Precompile for Bls12G1Msm { + fn address(&self) -> Address { + BLS12_G1MSM + } + + fn signature(&self, _: &[u8]) -> &'static str { + bls12G1MsmCall::SIGNATURE + } + + fn decode_call(&self, data: &[u8]) -> alloy_sol_types::Result> { + let pair_size = G1_POINT_SIZE + SCALAR_SIZE; + Ok(data.chunks(pair_size).map(hex::encode_prefixed).collect()) + } +} + +struct Bls12G2Add; +impl Precompile for Bls12G2Add { + fn address(&self) -> Address { + BLS12_G2ADD + } + + fn signature(&self, _: &[u8]) -> &'static str { + bls12G2AddCall::SIGNATURE + } + + fn decode_call(&self, data: &[u8]) -> alloy_sol_types::Result> { + let (p1, rest) = take_at_most(data, G2_POINT_SIZE); + let (p2, _) = take_at_most(rest, G2_POINT_SIZE); + Ok(vec![hex::encode_prefixed(p1), hex::encode_prefixed(p2)]) + } +} + +struct Bls12G2Msm; +impl Precompile for Bls12G2Msm { + fn address(&self) -> Address { + BLS12_G2MSM + } + + fn signature(&self, _: &[u8]) -> &'static str { + bls12G2MsmCall::SIGNATURE + } + + fn decode_call(&self, data: &[u8]) -> alloy_sol_types::Result> { + let pair_size = G2_POINT_SIZE + SCALAR_SIZE; + Ok(data.chunks(pair_size).map(hex::encode_prefixed).collect()) + } +} + +struct Bls12PairingCheck; +impl Precompile for Bls12PairingCheck { + fn address(&self) -> Address { + BLS12_PAIRING_CHECK + } + + fn signature(&self, _: &[u8]) -> &'static str { + bls12PairingCheckCall::SIGNATURE + } + + fn decode_call(&self, data: &[u8]) -> alloy_sol_types::Result> { + let pair_size = G1_POINT_SIZE + G2_POINT_SIZE; + Ok(data.chunks(pair_size).map(hex::encode_prefixed).collect()) + } + + fn decode_return(&self, data: &[u8]) -> alloy_sol_types::Result> { + let ret = bls12PairingCheckCall::abi_decode_returns(data)?; + Ok(vec![ret.to_string()]) + } +} + +struct Bls12MapFpToG1; +impl Precompile for Bls12MapFpToG1 { + fn address(&self) -> Address { + BLS12_MAP_FP_TO_G1 + } + + fn signature(&self, _: &[u8]) -> &'static str { + bls12MapFpToG1Call::SIGNATURE + } + + fn decode_call(&self, data: &[u8]) -> alloy_sol_types::Result> { + let (fp, _) = take_at_most(data, FP_SIZE); + Ok(vec![hex::encode_prefixed(fp)]) + } +} + +struct Bls12MapFp2ToG2; +impl Precompile for Bls12MapFp2ToG2 { + fn address(&self) -> Address { + BLS12_MAP_FP2_TO_G2 + } + + fn signature(&self, _: &[u8]) -> &'static str { + bls12MapFp2ToG2Call::SIGNATURE + } + + fn decode_call(&self, data: &[u8]) -> alloy_sol_types::Result> { + let (fp2, _) = take_at_most(data, G1_POINT_SIZE); + Ok(vec![hex::encode_prefixed(fp2)]) + } +} + +struct P256Verify; +impl Precompile for P256Verify { + fn address(&self) -> Address { + P256_VERIFY + } + + fn signature(&self, _: &[u8]) -> &'static str { + p256VerifyCall::SIGNATURE + } + + fn decode_call(&self, data: &[u8]) -> alloy_sol_types::Result> { + let p256VerifyCall { hash, r, s, qx, qy } = p256VerifyCall::abi_decode_raw(data)?; + Ok(vec![hash.to_string(), r.to_string(), s.to_string(), qx.to_string(), qy.to_string()]) + } + + fn decode_return(&self, data: &[u8]) -> alloy_sol_types::Result> { + let ret = p256VerifyCall::abi_decode_returns(data)?; + Ok(vec![ret.to_string()]) + } +} + +fn take_at_most(data: &[u8], n: usize) -> (&[u8], &[u8]) { + let n = n.min(data.len()); + data.split_at(n) +} + #[cfg(test)] mod tests { use super::*; diff --git a/crates/evm/traces/src/lib.rs b/crates/evm/traces/src/lib.rs index 301454d43eeab..5e8c452c8695a 100644 --- a/crates/evm/traces/src/lib.rs +++ b/crates/evm/traces/src/lib.rs @@ -204,7 +204,7 @@ pub fn render_trace_arena_inner( with_storage_changes: bool, ) -> String { if shell::is_json() { - return serde_json::to_string(&arena.resolve_arena()).expect("Failed to write traces"); + return serde_json::to_string(&arena.resolve_arena()).expect("Failed to serialize traces"); } let mut w = TraceWriter::new(Vec::::new()) diff --git a/crates/fmt/src/state/mod.rs b/crates/fmt/src/state/mod.rs index ada5eadd55bf0..762ecdb4ce645 100644 --- a/crates/fmt/src/state/mod.rs +++ b/crates/fmt/src/state/mod.rs @@ -61,7 +61,6 @@ impl CallContext { #[derive(Debug, Default)] pub(super) struct CallStack { stack: Vec, - precall_size: usize, } impl Deref for CallStack { @@ -80,14 +79,6 @@ impl CallStack { self.stack.pop() } - pub(crate) fn add_precall(&mut self, size: usize) { - self.precall_size += size; - } - - pub(crate) fn reset_precall(&mut self) { - self.precall_size = 0; - } - pub(crate) fn is_nested(&self) -> bool { self.last().is_some_and(|call| call.is_nested()) } diff --git a/crates/fmt/src/state/sol.rs b/crates/fmt/src/state/sol.rs index 52fb7fe0172f1..a8c9bd6647de1 100644 --- a/crates/fmt/src/state/sol.rs +++ b/crates/fmt/src/state/sol.rs @@ -795,12 +795,8 @@ impl<'ast> State<'_, 'ast> { fits_alone && !self.has_comment_between(rhs.span.lo(), rhs.span.hi()); let force_break = overflows && fits_alone_no_cmnts; - // Set up precall size tracking if lhs_size <= space_left { self.neverbreak(); - self.call_stack.add_precall(lhs_size + 1); - } else { - self.call_stack.add_precall(space_left + self.config.tab_width); } // Handle comments before the RHS expression @@ -932,7 +928,6 @@ impl<'ast> State<'_, 'ast> { } self.var_init = cache; - self.call_stack.reset_precall(); } fn print_var(&mut self, var: &'ast ast::VariableDefinition<'ast>, is_var_def: bool) { @@ -1955,12 +1950,6 @@ impl<'ast> State<'_, 'ast> { self.end(); self.word(" ="); - // '(' + var + ', ' + var + ')' + ' =' - let vars_size = vars.iter().fold(0, |acc, var| { - acc + var.as_ref().unspan().map_or(0, |v| self.estimate_size(v.span)) + 2 - }) + 2; - self.call_stack.add_precall(vars_size); - if self.estimate_size(init_expr.span) + self.config.tab_width <= std::cmp::max(space_left, self.space_left()) { diff --git a/crates/forge/Cargo.toml b/crates/forge/Cargo.toml index 515983876019c..8169750642c6c 100644 --- a/crates/forge/Cargo.toml +++ b/crates/forge/Cargo.toml @@ -88,6 +88,8 @@ watchexec-signals = "5.0" clearscreen = "4.0" evm-disassembler.workspace = true path-slash.workspace = true +reqwest = { workspace = true, features = ["json"] } +url.workspace = true # doc server axum = { workspace = true, features = ["ws"] } diff --git a/crates/forge/src/cmd/clone.rs b/crates/forge/src/cmd/clone.rs index 6cf3db9ff7ae9..97337907ac201 100644 --- a/crates/forge/src/cmd/clone.rs +++ b/crates/forge/src/cmd/clone.rs @@ -1,10 +1,13 @@ use super::{init::InitArgs, install::DependencyInstallOpts}; use alloy_primitives::{Address, Bytes, ChainId, TxHash}; -use clap::{Parser, ValueHint}; +use clap::{Parser, ValueEnum, ValueHint}; use eyre::Result; +use forge_verify::sourcify::SOURCIFY_URL; use foundry_block_explorers::{ Client, - contract::{ContractCreationData, ContractMetadata, Metadata}, + contract::{ + ContractCreationData, ContractMetadata, Metadata, SourceCodeEntry, SourceCodeMetadata, + }, errors::EtherscanError, }; use foundry_cli::{ @@ -22,11 +25,16 @@ use foundry_compilers::{ compilers::solc::Solc, }; use foundry_config::{Chain, Config}; +use reqwest::StatusCode; +use serde::Deserialize; use std::{ + collections::{BTreeMap, HashMap}, fs::read_dir, path::{Path, PathBuf}, time::Duration, }; +use tracing::trace; +use url::Url; /// CloneMetadata stores the metadata that are not included by `foundry.toml` but necessary for a /// cloned contract. The metadata can be serialized to a metadata file in the cloned project root. @@ -52,14 +60,25 @@ pub struct CloneMetadata { pub storage_layout: StorageLayout, } +/// Source explorer type for `forge clone`. +#[derive(Clone, Copy, Debug, ValueEnum, Default)] +pub enum SourceExplorer { + /// Use Etherscan API (default). + #[default] + Etherscan, + /// Use Sourcify API. + Sourcify, +} + /// CLI arguments for `forge clone`. /// -/// `forge clone` clones an on-chain contract from block explorers (e.g., Etherscan) in the -/// following steps: +/// `forge clone` clones an on-chain contract from block explorers (e.g., Etherscan, Sourcify) in +/// the following steps: /// 1. Fetch the contract source code from the block explorer. /// 2. Initialize a empty foundry project at the `root` directory specified in `CloneArgs`. /// 3. Dump the contract sources to the source directory. -/// 4. Update the `foundry.toml` configuration file with the compiler settings from Etherscan. +/// 4. Update the `foundry.toml` configuration file with the compiler settings from the block +/// explorer. /// 5. Try compile the cloned contract, so that we can get the original storage layout. This /// original storage layout is preserved in the `CloneMetadata` so that if the user later /// modifies the contract, it is possible to quickly check the storage layout compatibility with @@ -78,7 +97,7 @@ pub struct CloneArgs { #[arg(long)] pub no_remappings_txt: bool, - /// Keep the original directory structure collected from Etherscan. + /// Keep the original directory structure collected from the block explorer. /// /// If this flag is set, the directory structure of the cloned project will be kept as is. /// By default, the directory structure is re-orgnized to increase the readability, but may @@ -86,6 +105,18 @@ pub struct CloneArgs { #[arg(long)] pub keep_directory_structure: bool, + /// Source explorer to use for fetching contract data. + /// + /// Can be either "etherscan" (default) or "sourcify". + #[arg(long, default_value = "etherscan", value_name = "EXPLORER")] + pub source: SourceExplorer, + + /// Custom Sourcify API URL. + /// + /// Implies `--source sourcify`. + #[arg(long, value_name = "URL")] + pub sourcify_url: Option, + #[command(flatten)] pub etherscan: EtherscanOpts, @@ -95,19 +126,41 @@ pub struct CloneArgs { impl CloneArgs { pub async fn run(self) -> Result<()> { - let Self { address, root, install, etherscan, no_remappings_txt, keep_directory_structure } = - self; + let Self { + address, + root, + install, + etherscan, + no_remappings_txt, + keep_directory_structure, + source, + sourcify_url, + } = self; // step 0. get the chain and api key from the config let config = etherscan.load_config()?; let chain = config.chain.unwrap_or_default(); - let etherscan_api_key = config.get_etherscan_api_key(Some(chain)).unwrap_or_default(); - let client = Client::new(chain, etherscan_api_key.clone())?; - - // step 1. get the metadata from client - sh_println!("Downloading the source code of {address} from Etherscan...")?; - let meta = Self::collect_metadata_from_client(address, &client).await?; + // If sourcify_url is specified, use Sourcify as the source + let source = if sourcify_url.is_some() { SourceExplorer::Sourcify } else { source }; + + // step 1. get the metadata from client based on source type + let (meta, explorer_name, sourcify_client) = match source { + SourceExplorer::Etherscan => { + let etherscan_api_key = + config.get_etherscan_api_key(Some(chain)).unwrap_or_default(); + let client = Client::new(chain, etherscan_api_key.clone())?; + sh_println!("Downloading the source code of {address} from Etherscan...")?; + let meta = Self::collect_metadata_from_client(address, &client).await?; + (meta, "Etherscan", None) + } + SourceExplorer::Sourcify => { + let client = SourcifyClient::with_url(chain, sourcify_url.as_deref()); + sh_println!("Downloading the source code of {address} from Sourcify...")?; + let meta = Self::collect_metadata_from_client(address, &client).await?; + (meta, "Sourcify", Some(client)) + } + }; // step 2. initialize an empty project Self::init_an_empty_project(&root, install).await?; @@ -120,20 +173,31 @@ impl CloneArgs { .await?; // step 4. collect the compilation metadata - // if the etherscan api key is not set, we need to wait for 3 seconds between calls - sh_println!("Collecting the creation information of {address} from Etherscan...")?; - - if etherscan_api_key.is_empty() { - sh_warn!("Waiting for 5 seconds to avoid rate limit...")?; - tokio::time::sleep(Duration::from_secs(5)).await; + sh_println!("Collecting the creation information of {address} from {explorer_name}...")?; + + match source { + SourceExplorer::Etherscan => { + let etherscan_api_key = + config.get_etherscan_api_key(Some(chain)).unwrap_or_default(); + let client = Client::new(chain, etherscan_api_key.clone())?; + if etherscan_api_key.is_empty() { + sh_warn!("Waiting for 5 seconds to avoid rate limit...")?; + tokio::time::sleep(Duration::from_secs(5)).await; + } + Self::collect_compilation_metadata(&meta, chain, address, &root, &client).await?; + } + SourceExplorer::Sourcify => { + // Reuse the client from step 1 to benefit from cached creation data + let client = sourcify_client.expect("Sourcify client should exist"); + Self::collect_compilation_metadata(&meta, chain, address, &root, &client).await?; + } } - Self::collect_compilation_metadata(&meta, chain, address, &root, &client).await?; // step 5. git add and commit the changes if needed if install.commit { let git = Git::new(&root); git.add(Some("--all"))?; - let msg = format!("chore: forge clone {address}"); + let msg = format!("chore: forge clone {address} from {explorer_name}"); git.commit(&msg)?; } @@ -144,7 +208,7 @@ impl CloneArgs { /// /// * `address` - the address of the contract to be cloned. /// * `client` - the client of the block explorer. - pub(crate) async fn collect_metadata_from_client( + pub(crate) async fn collect_metadata_from_client( address: Address, client: &C, ) -> Result { @@ -175,12 +239,12 @@ impl CloneArgs { /// Collect the compilation metadata of the cloned contract. /// This function compiles the cloned contract and collects the compilation metadata. /// - /// * `meta` - the metadata of the contract (from Etherscan). + /// * `meta` - the metadata of the contract (from block explorer). /// * `chain` - the chain where the contract to be cloned locates. /// * `address` - the address of the contract to be cloned. /// * `root` - the root directory of the cloned project. /// * `client` - the client of the block explorer. - pub(crate) async fn collect_compilation_metadata( + pub(crate) async fn collect_compilation_metadata( meta: &Metadata, chain: Chain, address: Address, @@ -588,10 +652,10 @@ pub fn find_main_contract<'a>( rv.ok_or_else(|| eyre::eyre!("contract not found")) } -/// EtherscanClient is a trait that defines the methods to interact with Etherscan. +/// ExplorerClient is a trait that defines the methods to interact with block explorers. /// It is defined as a wrapper of the `foundry_block_explorers::Client` to allow mocking. #[cfg_attr(test, mockall::automock)] -pub(crate) trait EtherscanClient { +pub(crate) trait ExplorerClient { async fn contract_source_code( &self, address: Address, @@ -602,7 +666,7 @@ pub(crate) trait EtherscanClient { ) -> std::result::Result; } -impl EtherscanClient for Client { +impl ExplorerClient for Client { async fn contract_source_code( &self, address: Address, @@ -618,13 +682,322 @@ impl EtherscanClient for Client { } } +/// SourcifyClient is a client for interacting with Sourcify API. +pub(crate) struct SourcifyClient { + client: reqwest::Client, + chain: Chain, + base_url: String, + /// Whether the base_url already contains the full path (v2/contract/chain) + is_full_path: bool, + /// Cached creation data from the first API call + cached_creation_data: std::sync::Arc>>, +} + +impl SourcifyClient { + pub fn with_url(chain: Chain, verifier_url: Option<&str>) -> Self { + let (base_url, is_full_path) = match verifier_url { + Some(url) => ( + Url::parse(url).unwrap_or_else(|_| Url::parse(SOURCIFY_URL).unwrap()), + true, // Custom URL contains full path + ), + None => (Url::parse(SOURCIFY_URL).unwrap(), false), + }; + Self { + client: reqwest::Client::new(), + chain, + base_url: base_url.to_string().trim_end_matches('/').to_string(), + is_full_path, + cached_creation_data: std::sync::Arc::new(std::sync::Mutex::new(None)), + } + } + + fn get_contract_url(&self, address: Address, fields: &str) -> String { + if self.is_full_path { + // Custom URL already contains v2/contract/chain, just append address and fields + format!("{}/{}?fields={}", self.base_url, address, fields) + } else { + // Default URL, need to build full path + format!( + "{}/v2/contract/{}/{}?fields={}", + self.base_url, + self.chain.id(), + address, + fields + ) + } + } +} + +/// Sourcify API response for contract files. +#[derive(Debug, Clone, Deserialize)] +#[serde(untagged)] +#[allow(dead_code, clippy::large_enum_variant)] +enum SourcifyContractResponse { + Success(SourcifyContractData), + Error(SourcifyErrorResponse), +} + +#[derive(Debug, Clone, Deserialize)] +#[serde(rename_all = "camelCase")] +struct SourcifyContractData { + #[serde(default)] + sources: Option>, + #[serde(default)] + abi: Option, + #[serde(default)] + compilation: Option, + #[serde(default)] + #[allow(dead_code)] + creation_code: Option, + #[serde(default)] + #[allow(dead_code)] + deployed_bytecode: Option, + #[serde(default)] + #[allow(dead_code)] + runtime_bytecode: Option, + #[serde(default)] + deployment: Option, + // Additional fields that may be present in the response + #[serde(default)] + #[allow(dead_code)] + match_id: Option, + #[serde(default)] + #[allow(dead_code)] + creation_match: Option, + #[serde(default)] + #[allow(dead_code)] + runtime_match: Option, + #[serde(default)] + #[allow(dead_code)] + verified_at: Option, + #[serde(default)] + #[allow(dead_code)] + r#match: Option, + #[serde(default)] + #[allow(dead_code)] + chain_id: Option, + #[serde(default)] + #[allow(dead_code)] + address: Option, +} + +#[derive(Debug, Clone, Deserialize)] +#[serde(rename_all = "camelCase")] +struct SourcifySourceFile { + #[serde(default)] + content: String, +} + +#[derive(Debug, Clone, Deserialize)] +#[serde(rename_all = "camelCase")] +struct SourcifyCompilation { + #[serde(default)] + compiler_version: String, + #[serde(default)] + name: String, + #[serde(default)] + compiler_settings: Option, +} + +#[derive(Debug, Clone, Deserialize)] +#[serde(rename_all = "camelCase")] +struct SourcifyDeployment { + #[serde(default)] + transaction_hash: Option, + #[serde(default)] + deployer: Option, +} + +#[derive(Debug, Clone, Deserialize)] +#[serde(rename_all = "camelCase")] +struct SourcifyErrorResponse { + #[serde(default)] + custom_code: String, + #[serde(default)] + message: String, + #[serde(default)] + #[allow(dead_code)] + error_id: String, + // Error responses should not have sources field + #[serde(default)] + #[serde(skip_serializing_if = "Option::is_none")] + #[allow(dead_code)] + sources: Option<()>, +} + +impl ExplorerClient for SourcifyClient { + async fn contract_source_code( + &self, + address: Address, + ) -> std::result::Result { + // Request all fields including creation data to cache them + let url = self.get_contract_url(address, "sources,abi,compilation,deployment"); + let response = self.client.get(&url).send().await?; + + let status = response.status(); + trace!("Sourcify API response: status={:?}, url={}", status, url); + + match status { + StatusCode::NOT_FOUND => return Err(EtherscanError::ContractCodeNotVerified(address)), + StatusCode::TOO_MANY_REQUESTS => return Err(EtherscanError::RateLimitExceeded), + _ => {} + } + + // Read response body once + let response_text = response.text().await?; + trace!("Sourcify API response body: {}", response_text); + + if !status.is_success() { + return Err(EtherscanError::Unknown(format!( + "Sourcify API error (status {status}): {response_text}" + ))); + } + + // Use the untagged enum to properly handle both success and error responses + let response: SourcifyContractResponse = + serde_json::from_str(&response_text).map_err(|e| { + // Truncate response for error message to avoid huge output + let truncated = if response_text.len() > 500 { + format!("{}... (truncated)", &response_text[..500]) + } else { + response_text.clone() + }; + EtherscanError::Unknown(format!( + "Failed to parse Sourcify response: {e}. Response: {truncated}" + )) + })?; + + let data = match response { + SourcifyContractResponse::Success(data) => data, + SourcifyContractResponse::Error(error) => { + let error_msg = if error.custom_code.is_empty() && error.message.is_empty() { + "Unknown Sourcify API error".to_string() + } else { + format!("Sourcify API error: {} - {}", error.custom_code, error.message) + }; + return Err(EtherscanError::Unknown(error_msg)); + } + }; + + let sources_map = data.sources.ok_or_else(|| { + EtherscanError::Unknown("Sourcify response missing sources field".to_string()) + })?; + + // Convert sources map to SourceCodeMetadata::Sources format + let sources: HashMap = sources_map + .into_iter() + .map(|(path, source_file)| (path, SourceCodeEntry { content: source_file.content })) + .collect(); + + let source_code = SourceCodeMetadata::Sources(sources); + + let contract_name = data + .compilation + .as_ref() + .map(|c| c.name.clone()) + .unwrap_or_else(|| "Contract".to_string()); + + let compiler_version = + data.compilation.as_ref().map(|c| c.compiler_version.clone()).unwrap_or_default(); + + let abi = data.abi.map(|a| a.to_string()).unwrap_or_default(); + + // Cache creation data for later use in contract_creation_data + let tx_hash = data + .deployment + .as_ref() + .and_then(|d| d.transaction_hash.as_ref()) + .and_then(|h| h.parse().ok()) + .unwrap_or(TxHash::ZERO); + let creator = data + .deployment + .as_ref() + .and_then(|d| d.deployer.as_ref()) + .and_then(|a| a.parse().ok()) + .unwrap_or(Address::ZERO); + let creation_data = ContractCreationData { + contract_address: address, + contract_creator: creator, + transaction_hash: tx_hash, + }; + if let Ok(mut cache) = self.cached_creation_data.lock() { + *cache = Some(creation_data); + } + + // Extract compiler_settings from compilation if available + let constructor_arguments = Bytes::default(); + let optimization_used = data + .compilation + .as_ref() + .and_then(|c| c.compiler_settings.as_ref()) + .and_then(|s| s.get("optimizer")) + .and_then(|o| o.get("enabled")) + .and_then(|e| e.as_bool()) + .map(|b| if b { 1 } else { 0 }) + .unwrap_or(0); + + let runs = data + .compilation + .as_ref() + .and_then(|c| c.compiler_settings.as_ref()) + .and_then(|s| s.get("optimizer")) + .and_then(|o| o.get("runs")) + .and_then(|r| r.as_u64()) + .unwrap_or(0); + + Ok(ContractMetadata { + items: vec![Metadata { + source_code, + abi, + contract_name, + compiler_version, + optimization_used, + runs, + constructor_arguments, + evm_version: String::new(), + library: String::new(), + license_type: String::new(), + proxy: 0, + implementation: None, + swarm_source: String::new(), + }], + }) + } + + async fn contract_creation_data( + &self, + address: Address, + ) -> std::result::Result { + // Check cache first + if let Ok(cache) = self.cached_creation_data.lock() + && let Some(ref cached_data) = *cache + && cached_data.contract_address == address + { + return Ok(*cached_data); + } + + // If cache is empty or address doesn't match, use fallback values + // This should rarely happen since we cache in contract_source_code + trace!("Creation data not in cache for address {address}, using fallback values"); + let creation_data = ContractCreationData { + contract_address: address, + contract_creator: Address::ZERO, + transaction_hash: TxHash::ZERO, + }; + if let Ok(mut cache) = self.cached_creation_data.lock() { + *cache = Some(creation_data); + } + + Ok(creation_data) + } +} + #[cfg(test)] mod tests { use super::*; use alloy_primitives::hex; use foundry_compilers::CompilerContract; use foundry_test_utils::rpc::next_etherscan_api_key; - use std::collections::BTreeMap; #[expect(clippy::disallowed_macros)] fn assert_successful_compilation(root: &PathBuf) -> ProjectCompileOutput { @@ -652,7 +1025,7 @@ mod tests { }); } - fn mock_etherscan(address: Address) -> impl super::EtherscanClient { + fn mock_etherscan(address: Address) -> impl super::ExplorerClient { // load mock data let mut mocked_data = BTreeMap::new(); let data_folder = @@ -679,7 +1052,7 @@ mod tests { let (metadata, creation_data) = mocked_data.get(&address).unwrap(); let metadata = metadata.clone(); let creation_data = *creation_data; - let mut mocked_client = super::MockEtherscanClient::new(); + let mut mocked_client = super::MockExplorerClient::new(); mocked_client .expect_contract_source_code() .times(1) diff --git a/crates/forge/tests/cli/cmd.rs b/crates/forge/tests/cli/cmd.rs index 844caaa5f15a0..e0b2c43c499ac 100644 --- a/crates/forge/tests/cli/cmd.rs +++ b/crates/forge/tests/cli/cmd.rs @@ -742,6 +742,33 @@ forgetest!(can_clone_quiet, |prj, cmd| { .assert_empty_stdout(); }); +// checks that clone works with sourcify +forgetest!(can_clone_sourcify, |prj, cmd| { + prj.wipe(); + + let foundry_toml = prj.root().join(Config::FILE_NAME); + assert!(!foundry_toml.exists()); + + cmd.args(["clone", "--source", "sourcify", "0xDb53f47aC61FE54F456A4eb3E09832D08Dd7BEec"]) + .arg(prj.root()) + .assert_success() + .stdout_eq(str![[r#" +Downloading the source code of 0xDb53f47aC61FE54F456A4eb3E09832D08Dd7BEec from Sourcify... +Initializing [..]... +Installing forge-std in [..] (url: https://github.com/foundry-rs/forge-std, tag: None) + Installed forge-std[..] + Initialized forge project +Collecting the creation information of 0xDb53f47aC61FE54F456A4eb3E09832D08Dd7BEec from Sourcify... +[COMPILING_FILES] with [SOLC_VERSION] +[SOLC_VERSION] [ELAPSED] +Compiler run successful! + +"#]]); + + let s = read_string(&foundry_toml); + let _config: BasicConfig = parse_with_profile(&s).unwrap().unwrap().1; +}); + // checks that clone works with --no-remappings-txt forgetest!(can_clone_no_remappings_txt, |prj, cmd| { prj.wipe(); diff --git a/crates/forge/tests/cli/precompiles.rs b/crates/forge/tests/cli/precompiles.rs index 3ffda2d5ce414..505a6f7b04800 100644 --- a/crates/forge/tests/cli/precompiles.rs +++ b/crates/forge/tests/cli/precompiles.rs @@ -3,6 +3,178 @@ use foundry_evm_networks::NetworkConfigs; use foundry_test_utils::str; +forgetest_init!(precompile_trace_decoding, |prj, cmd| { + prj.add_test( + "PrecompileTrace.t.sol", + r#" +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import "forge-std/Test.sol"; + +contract PrecompileCaller { + constructor() { + // 0x01 - ECRECOVER + { + bytes32 hash = keccak256("test message"); + uint8 v = 27; + bytes32 r = bytes32(uint256(1)); + bytes32 s = bytes32(uint256(2)); + address(0x01).staticcall(abi.encode(hash, v, r, s)); + } + + // 0x02 - SHA256 + address(0x02).staticcall(abi.encodePacked("hello")); + + // 0x03 - RIPEMD160 + address(0x03).staticcall(abi.encodePacked("hello")); + + // 0x04 - IDENTITY (datacopy) + address(0x04).staticcall(abi.encodePacked("hello")); + + // 0x05 - MODEXP: compute 2^3 mod 5 = 3 + { + bytes memory modexpInput = abi.encodePacked( + uint256(1), // base length + uint256(1), // exponent length + uint256(1), // modulus length + uint8(2), // base = 2 + uint8(3), // exponent = 3 + uint8(5) // modulus = 5 + ); + address(0x05).staticcall(modexpInput); + } + + // 0x06 - BN254 ADD (ecadd): P + O = P + { + uint256 g1x = 1; + uint256 g1y = 2; + uint256 zerox = 0; + uint256 zeroy = 0; + address(0x06).staticcall(abi.encode(g1x, g1y, zerox, zeroy)); + } + + // 0x07 - BN254 MUL (ecmul): 1 * G = G + { + uint256 g1x = 1; + uint256 g1y = 2; + uint256 scalar = 1; + address(0x07).staticcall(abi.encode(g1x, g1y, scalar)); + } + + // 0x08 - BN254 PAIRING: empty input returns success (1) + address(0x08).staticcall(""); + + // 0x09 - BLAKE2F + { + bytes memory blake2fInput = new bytes(213); + blake2fInput[3] = 0x0c; // 12 rounds + bytes8[8] memory iv = [ + bytes8(0x6a09e667f3bcc908), + bytes8(0xbb67ae8584caa73b), + bytes8(0x3c6ef372fe94f82b), + bytes8(0xa54ff53a5f1d36f1), + bytes8(0x510e527fade682d1), + bytes8(0x9b05688c2b3e6c1f), + bytes8(0x1f83d9abfb41bd6b), + bytes8(0x5be0cd19137e2179) + ]; + for (uint256 i = 0; i < 8; i++) { + for (uint256 j = 0; j < 8; j++) { + blake2fInput[4 + i * 8 + j] = iv[i][j]; + } + } + blake2fInput[212] = 0x01; + address(0x09).staticcall(blake2fInput); + } + + // 0x0B - BLS12-381 G1 ADD (two points at infinity) + address(0x0B).staticcall(new bytes(256)); + + // 0x0C - BLS12-381 G1 MSM + address(0x0C).staticcall(new bytes(160)); + + // 0x0D - BLS12-381 G2 ADD (two points at infinity) + address(0x0D).staticcall(new bytes(512)); + + // 0x0E - BLS12-381 G2 MSM + address(0x0E).staticcall(new bytes(288)); + + // 0x0F - BLS12-381 PAIRING (G1 + G2 infinity points) + address(0x0F).staticcall(new bytes(384)); + + // 0x10 - BLS12-381 MAP FP TO G1 + address(0x10).staticcall(new bytes(64)); + + // 0x11 - BLS12-381 MAP FP2 TO G2 + address(0x11).staticcall(new bytes(128)); + + // 0x100 - P256VERIFY (secp256r1) + address(0x100).staticcall(new bytes(160)); + } +} + +contract PrecompileTraceTest is Test { + function test_precompile_traces() public { + new PrecompileCaller(); + } +} + "#, + ); + + cmd.args(["test", "--mt", "test_precompile_traces", "-vvvv", "--evm-version", "osaka"]) + .assert_success() + .stdout_eq(str![[r#" +... +Ran 1 test for test/PrecompileTrace.t.sol:PrecompileTraceTest +[PASS] test_precompile_traces() ([GAS]) +Traces: + [..] PrecompileTraceTest::test_precompile_traces() + ├─ [..] → new PrecompileCaller@[..] + │ ├─ [..] PRECOMPILES::ecrecover(0xea83cdcdd06bf61e414054115a551e23133711d0507dcbc07a4bab7dc4581935, 27, 1, 2) [staticcall] + │ │ └─ ← [Return] 0xBe038042508C42Df7b2A529cd4Cc0a9447c7D2b6 + │ ├─ [..] PRECOMPILES::sha256(0x68656c6c6f) [staticcall] + │ │ └─ ← [Return] 0x2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824 + │ ├─ [..] PRECOMPILES::ripemd(0x68656c6c6f) [staticcall] + │ │ └─ ← [Return] 0x000000000000000000000000108f07b838241261 + │ ├─ [..] PRECOMPILES::identity(0x68656c6c6f) [staticcall] + │ │ └─ ← [Return] 0x68656c6c6f + │ ├─ [..] PRECOMPILES::modexp(1, 1, 1, 0x02, 0x03, 0x05) [staticcall] + │ │ └─ ← [Return] 0x03 + │ ├─ [..] PRECOMPILES::ecadd(1, 2, 0, 0) [staticcall] + │ │ └─ ← [Return] (1, 2) + │ ├─ [..] PRECOMPILES::ecmul(1, 2, 1) [staticcall] + │ │ └─ ← [Return] (1, 2) + │ ├─ [..] PRECOMPILES::ecpairing() [staticcall] + │ │ └─ ← [Return] true + │ ├─ [..] PRECOMPILES::blake2f(12, [633244976228469098, 4298627039875721147, 3168446158426304060, 17381112106731261861, 15096882533739138641, 2264253069420660123, 7763433881832358687, 8728396173323133019], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0], 1) [staticcall] + │ │ └─ ← [Return] 0x1a48bfec594a1b13bb024be345656b8af895d662ccbc3f39fb5ecf2ef05942b5acace594cb81cdff6044b5bfaabfea105168676ce5753f6bb559ce3f92ad4850 + │ ├─ [..] PRECOMPILES::bls12G1Add(0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) [staticcall] + │ │ └─ ← [Return] 0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + │ ├─ [..] PRECOMPILES::bls12G1Msm(0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) [staticcall] + │ │ └─ ← [Return] 0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + │ ├─ [..] PRECOMPILES::bls12G2Add(0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000, 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) [staticcall] + │ │ └─ ← [Return] 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + │ ├─ [..] PRECOMPILES::bls12G2Msm(0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) [staticcall] + │ │ └─ ← [Return] 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + │ ├─ [..] PRECOMPILES::bls12PairingCheck(0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) [staticcall] + │ │ └─ ← [Return] true + │ ├─ [..] PRECOMPILES::bls12MapFpToG1(0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) [staticcall] + │ │ └─ ← [Return] 0x0000000000000000000000000000000011a9a0372b8f332d5c30de9ad14e50372a73fa4c45d5f2fa5097f2d6fb93bcac592f2e1711ac43db0519870c7d0ea41500000000000000000000000000000000092c0f994164a0719f51c24ba3788de240ff926b55f58c445116e8bc6a47cd63392fd4e8e22bdf9feaa96ee773222133 + │ ├─ [..] PRECOMPILES::bls12MapFp2ToG2(0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000) [staticcall] + │ │ └─ ← [Return] 0x00000000000000000000000000000000018320896ec9eef9d5e619848dc29ce266f413d02dd31d9b9d44ec0c79cd61f18b075ddba6d7bd20b7ff27a4b324bfce000000000000000000000000000000000a67d12118b5a35bb02d2e86b3ebfa7e23410db93de39fb06d7025fa95e96ffa428a7a27c3ae4dd4b40bd251ac658892000000000000000000000000000000000260e03644d1a2c321256b3246bad2b895cad13890cbe6f85df55106a0d334604fb143c7a042d878006271865bc359410000000000000000000000000000000004c69777a43f0bda07679d5805e63f18cf4e0e7c6112ac7f70266d199b4f76ae27c6269a3ceebdae30806e9a76aadf5c + │ ├─ [..] P256VERIFY::fulfillBasicOrder_efficient_6GL6yc() [staticcall] + │ │ └─ ← [Return] + │ └─ ← [Return] 62 bytes of code + └─ ← [Stop] + +Suite result: ok. 1 passed; 0 failed; 0 skipped; [ELAPSED] + +Ran 1 test suite [ELAPSED]: 1 tests passed, 0 failed, 0 skipped (1 total tests) + +"#]]); +}); + // tests transfer using celo precompile. // forgetest_init!(celo_transfer, |prj, cmd| { diff --git a/crates/primitives/src/network/receipt.rs b/crates/primitives/src/network/receipt.rs index d671dbb3d5535..9facb404b8c87 100644 --- a/crates/primitives/src/network/receipt.rs +++ b/crates/primitives/src/network/receipt.rs @@ -6,6 +6,7 @@ use alloy_serde::WithOtherFields; use derive_more::AsRef; use op_alloy_consensus::{OpDepositReceipt, OpDepositReceiptWithBloom}; use serde::{Deserialize, Serialize}; +use tempo_primitives::TEMPO_TX_TYPE_ID; use crate::FoundryReceiptEnvelope; @@ -118,6 +119,7 @@ impl TryFrom for FoundryTxReceipt { 0x02 => FoundryReceiptEnvelope::Eip1559(receipt_with_bloom), 0x03 => FoundryReceiptEnvelope::Eip4844(receipt_with_bloom), 0x04 => FoundryReceiptEnvelope::Eip7702(receipt_with_bloom), + TEMPO_TX_TYPE_ID => FoundryReceiptEnvelope::Tempo(receipt_with_bloom), 0x7E => { // Construct the deposit receipt, extracting optional deposit fields // These fields may not be present in all receipts, so missing/invalid diff --git a/crates/verify/src/lib.rs b/crates/verify/src/lib.rs index 85f8a7a1c830e..8e78c1bffde5f 100644 --- a/crates/verify/src/lib.rs +++ b/crates/verify/src/lib.rs @@ -19,7 +19,7 @@ pub use bytecode::VerifyBytecodeArgs; pub mod retry; pub use retry::RetryArgs; -mod sourcify; +pub mod sourcify; pub mod verify; pub use verify::{VerifierArgs, VerifyArgs, VerifyCheckArgs}; diff --git a/npm/env.d.ts b/npm/env.d.ts index 6df532a23210a..828acd8e5a17b 100644 --- a/npm/env.d.ts +++ b/npm/env.d.ts @@ -25,8 +25,8 @@ interface ImportMetaEnv { readonly VERSION_NAME: string // release.yml#jobs:release:strategy:matrix:include:-|platform readonly PLATFORM_NAME: 'linux' | 'darwin' | 'win32' - // `debug` / `release` / `maxperf` # <- always `maxperf` - readonly PROFILE: 'debug' | 'release' | 'maxperf' + // `debug` / `release` / `maxperf` / `dist` + readonly PROFILE: 'debug' | 'release' | 'maxperf' | 'dist' // Used for local testing/development only readonly REGISTRY_URL: string diff --git a/npm/src/const.mjs b/npm/src/const.mjs index d07978918c4eb..e606759888acb 100644 --- a/npm/src/const.mjs +++ b/npm/src/const.mjs @@ -5,7 +5,7 @@ import { URL } from 'node:url' * @typedef {'amd64' | 'arm64'} Arch * @typedef {'linux' | 'darwin' | 'win32'} Platform * @typedef {'forge' | 'cast' | 'anvil' | 'chisel'} Tool - * @typedef {'debug' | 'release' | 'maxperf'} Profile + * @typedef {'debug' | 'release' | 'maxperf' | 'dist'} Profile */ /** @type {readonly Tool[]} */ diff --git a/testdata/default/cheats/RecordLogs.t.sol b/testdata/default/cheats/RecordLogs.t.sol index 5927d5af23866..a21e7f0a06304 100644 --- a/testdata/default/cheats/RecordLogs.t.sol +++ b/testdata/default/cheats/RecordLogs.t.sol @@ -188,6 +188,41 @@ contract RecordLogsTest is Test { assertEq(entries[2].emitter, emitter2.getEmitterAddr()); } + function testRecordedLogsJson() public { + bytes memory testData = "Event Data in String"; + + vm.recordLogs(); + emitter.emitEvent(1, 2, 3, testData); + string memory logsJson = vm.getRecordedLogsJson(); + + // Verify JSON structure and values + assertGt(bytes(logsJson).length, 0); + + // Verify emitter address + string memory emitterAddr = vm.parseJsonString(logsJson, "[0].emitter"); + assertEq(vm.parseAddress(emitterAddr), address(emitter)); + + // Verify topics - first topic is event signature + string[] memory topics = vm.parseJsonStringArray(logsJson, "[0].topics"); + assertEq(topics.length, 4); + assertEq(vm.parseBytes32(topics[0]), keccak256("LogTopic123(uint256,uint256,uint256,bytes)")); + assertEq(vm.parseBytes32(topics[1]), bytes32(uint256(1))); + assertEq(vm.parseBytes32(topics[2]), bytes32(uint256(2))); + assertEq(vm.parseBytes32(topics[3]), bytes32(uint256(3))); + + // Verify data is hex-encoded + string memory data = vm.parseJsonString(logsJson, "[0].data"); + assertGt(bytes(data).length, 2); // At least "0x" + } + + function testRecordedLogsJsonEmpty() public { + vm.recordLogs(); + string memory logsJson = vm.getRecordedLogsJson(); + + // Empty array + assertEq(logsJson, "[]"); + } + function testRecordsConsumednAsRead() public { Vm.Log[] memory entries; diff --git a/testdata/utils/Vm.sol b/testdata/utils/Vm.sol index 8cced251493aa..e06ed8facda10 100644 --- a/testdata/utils/Vm.sol +++ b/testdata/utils/Vm.sol @@ -319,6 +319,7 @@ interface Vm { function getNonce(Wallet calldata wallet) external view returns (uint64 nonce); function getRawBlockHeader(uint256 blockNumber) external view returns (bytes memory rlpHeader); function getRecordedLogs() external view returns (Log[] memory logs); + function getRecordedLogsJson() external view returns (string memory logsJson); function getStateDiff() external view returns (string memory diff); function getStateDiffJson() external view returns (string memory diff); function getStorageAccesses() external view returns (StorageAccess[] memory storageAccesses); From 9c5e4e72529aa6115bad2be1ca80aaaaf4b0b024 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Fri, 16 Jan 2026 11:09:24 +0700 Subject: [PATCH 201/232] Potential fix for code scanning alert no. 103: Artifact poisoning (#336) Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> --- .github/workflows/npm.yml | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/.github/workflows/npm.yml b/.github/workflows/npm.yml index ae5642a6e1baf..0ab853e0520d0 100644 --- a/.github/workflows/npm.yml +++ b/.github/workflows/npm.yml @@ -233,9 +233,46 @@ jobs: PLATFORM='${{ matrix.os }}' ARCH='${{ matrix.arch }}' + # Basic validation of matrix-derived values to avoid path manipulation + case "$TOOL" in + (*[!a-zA-Z0-9_-]*|'') echo "ERROR: Invalid TOOL value: $TOOL" >&2; exit 1 ;; + esac + case "$PLATFORM" in + (*[!a-zA-Z0-9_-]*|'') echo "ERROR: Invalid PLATFORM value: $PLATFORM" >&2; exit 1 ;; + esac + case "$ARCH" in + (*[!a-zA-Z0-9_-]*|'') echo "ERROR: Invalid ARCH value: $ARCH" >&2; exit 1 ;; + esac + PACKAGE_DIR="./@foundry-rs/${TOOL}-${PLATFORM}-${ARCH}" + echo "Preparing to publish package from: $PACKAGE_DIR" + + if [[ ! -d "$PACKAGE_DIR" ]]; then + echo "ERROR: Package directory does not exist: $PACKAGE_DIR" >&2 + exit 1 + fi + + # Resolve to an absolute path and ensure it stays within ./@foundry-rs + ABS_PACKAGE_DIR="$(realpath "$PACKAGE_DIR")" + ABS_EXPECTED_ROOT="$(realpath "./@foundry-rs")" + case "$ABS_PACKAGE_DIR" in + "$ABS_EXPECTED_ROOT"/*) ;; + *) + echo "ERROR: Resolved package directory is outside expected root:" >&2 + echo " ABS_PACKAGE_DIR=$ABS_PACKAGE_DIR" >&2 + echo " ABS_EXPECTED_ROOT=$ABS_EXPECTED_ROOT" >&2 + exit 1 + ;; + esac + ls -la "$PACKAGE_DIR" + # Minimal sanity check: require a package.json before publishing + if [[ ! -f "$PACKAGE_DIR/package.json" ]]; then + echo "ERROR: package.json not found in $PACKAGE_DIR; refusing to publish." >&2 + exit 1 + fi + bun ./scripts/publish.mjs "$PACKAGE_DIR" echo "Published @foundry-rs/${TOOL}-${PLATFORM}-${ARCH}" From 2ad832aab599625b84a446e3c6b041a920086dd8 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Fri, 23 Jan 2026 08:11:49 +0700 Subject: [PATCH 202/232] Create Docker.yml (#338) Build: Introduce a Docker GitHub Actions workflow that logs into Docker Hub, builds images with buildx, tags them based on branch, semver, and SHA, and pushes them on non-PR events while only loading them for pull requests. Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- .github/workflows/Docker.yml | 62 ++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 .github/workflows/Docker.yml diff --git a/.github/workflows/Docker.yml b/.github/workflows/Docker.yml new file mode 100644 index 0000000000000..5a2330e7d5d62 --- /dev/null +++ b/.github/workflows/Docker.yml @@ -0,0 +1,62 @@ +name: Docker + +on: + push: + tags: ["*"] + branches: + - "main" + pull_request: + branches: ["**"] + +env: + # Hostname of your registry + REGISTRY: docker.io + # Image repository, without hostname and tag + IMAGE_NAME: ${{ github.repository }} + SHA: ${{ github.event.pull_request.head.sha || github.event.after }} + +jobs: + build: + runs-on: ubuntu-latest + permissions: + pull-requests: write + + steps: + # Authenticate to the container registry + - name: Authenticate to registry ${{ env.REGISTRY }} + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ secrets.REGISTRY_USER }} + password: ${{ secrets.REGISTRY_TOKEN }} + + - name: Setup Docker buildx + uses: docker/setup-buildx-action@v3 + + # Extract metadata (tags, labels) for Docker + - name: Extract Docker metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + labels: | + org.opencontainers.image.revision=${{ env.SHA }} + tags: | + type=edge,branch=$repo.default_branch + type=semver,pattern=v{{version}} + type=sha,prefix=,suffix=,format=short + + # Build and push Docker image with Buildx + # (don't push on PR, load instead) + - name: Build and push Docker image + id: build-and-push + uses: docker/build-push-action@v6 + with: + sbom: ${{ github.event_name != 'pull_request' }} + provenance: ${{ github.event_name != 'pull_request' }} + push: ${{ github.event_name != 'pull_request' }} + load: ${{ github.event_name == 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max From e3d4029ef71342a1344f9b5b84cd112f4631927b Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Fri, 23 Jan 2026 09:23:49 +0700 Subject: [PATCH 203/232] Potential fix for code scanning alert no. 108: Artifact poisoning (#345) Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> --- .github/workflows/npm.yml | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/.github/workflows/npm.yml b/.github/workflows/npm.yml index 0ab853e0520d0..6ef9898e62587 100644 --- a/.github/workflows/npm.yml +++ b/.github/workflows/npm.yml @@ -226,6 +226,7 @@ jobs: RELEASE_VERSION: ${{ steps.release-version.outputs.RELEASE_VERSION }} NPM_TOKEN: ${{ secrets.NPM_TOKEN }} NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + ARTIFACT_DIR: ${{ steps.paths.outputs.artifact_dir }} run: | set -euo pipefail @@ -245,7 +246,21 @@ jobs: esac PACKAGE_DIR="./@foundry-rs/${TOOL}-${PLATFORM}-${ARCH}" - echo "Preparing to publish package from: $PACKAGE_DIR" + EXPECTED_PKG_NAME="${TOOL}-${PLATFORM}-${ARCH}" + + # Ensure corresponding artifact directory exists in the isolated artifact dir + if [[ -z "${ARTIFACT_DIR:-}" ]]; then + echo "ERROR: ARTIFACT_DIR is not set; refusing to publish." >&2 + exit 1 + fi + + EXPECTED_ARTIFACT_PATH="${ARTIFACT_DIR}/${EXPECTED_PKG_NAME}" + if [[ ! -d "$EXPECTED_ARTIFACT_PATH" ]]; then + echo "ERROR: Expected artifact directory not found at: $EXPECTED_ARTIFACT_PATH" >&2 + exit 1 + fi + + echo "Preparing to publish package from: $PACKAGE_DIR (artifact: $EXPECTED_ARTIFACT_PATH)" if [[ ! -d "$PACKAGE_DIR" ]]; then echo "ERROR: Package directory does not exist: $PACKAGE_DIR" >&2 From b8eb87b1129ee13407177b2500dc93e00be182a4 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Mon, 26 Jan 2026 19:46:11 +0700 Subject: [PATCH 204/232] Potential fix for code scanning alert no. 110: Uncontrolled data used in path expression (#347) Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> --- crates/test-utils/src/script.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/test-utils/src/script.rs b/crates/test-utils/src/script.rs index 07413fef5495c..f20dae571cef3 100644 --- a/crates/test-utils/src/script.rs +++ b/crates/test-utils/src/script.rs @@ -118,6 +118,7 @@ impl ScriptTester { fn copy_testdata(root: &Path) -> Result<()> { let testdata = Self::testdata_path(); let from_dir = testdata.join("utils"); + let canonical_from_dir = from_dir.canonicalize()?; let to_dir = root.join("utils"); fs::create_dir_all(&to_dir)?; for entry in fs::read_dir(&from_dir)? { @@ -138,9 +139,9 @@ impl ScriptTester { // Skip invalid (potentially dangerous) file names continue; } - // Verify canonicalized file is in from_dir to avoid symlink traversal + // Verify canonicalized file is in canonical_from_dir to avoid symlink traversal if let Ok(canonical_file) = file.canonicalize() { - if !canonical_file.starts_with(&from_dir) { + if !canonical_file.starts_with(&canonical_from_dir) { continue; } } else { From c97ebb32ec4b5f84897f9048488a94b2959e9cab Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Wed, 28 Jan 2026 00:07:31 +0700 Subject: [PATCH 205/232] benches\LATEST.md --- benches/LATEST.md | 71 +--- sleep.json | 955 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 968 insertions(+), 58 deletions(-) create mode 100644 sleep.json diff --git a/benches/LATEST.md b/benches/LATEST.md index 7ea1049a2ac41..2ddf3b8c922f1 100644 --- a/benches/LATEST.md +++ b/benches/LATEST.md @@ -1,73 +1,28 @@ # Foundry Benchmark Results -**Date**: 2025-10-02 12:14:23 +**Date**: 2026-01-27 03:38:34 -## Repositories Tested +## Summary -1. [ithacaxyz/account](https://github.com/ithacaxyz/account) -2. [Vectorized/solady](https://github.com/Vectorized/solady) -3. [Uniswap/v4-core](https://github.com/Uniswap/v4-core) -4. [sparkdotfi/spark-psm](https://github.com/sparkdotfi/spark-psm) - -## Foundry Versions - -- **v1.3.6**: forge Version: 1.3.6-v1.3.6 (d241588 2025-09-16) -- **v1.4.0-rc1**: forge Version: 1.4.0-v1.4.0-rc1 (bd0e4a7 2025-10-01) - -## Forge Test - -| Repository | v1.3.6 | v1.4.0-rc1 | -| -------------------- | ------- | ---------- | -| ithacaxyz-account | 3.17 s | 2.94 s | -| solady | 2.28 s | 2.10 s | -| Uniswap-v4-core | 7.27 s | 6.13 s | -| sparkdotfi-spark-psm | 43.04 s | 44.08 s | +Benchmarked 2 Foundry versions across 1 repositories. -## Forge Fuzz Test +### Repositories Tested -| Repository | v1.3.6 | v1.4.0-rc1 | -| -------------------- | ------ | ---------- | -| ithacaxyz-account | 3.18 s | 3.02 s | -| solady | 2.39 s | 2.24 s | -| Uniswap-v4-core | 6.84 s | 6.20 s | -| sparkdotfi-spark-psm | 3.07 s | 2.72 s | - -## Forge Test (Isolated) - -| Repository | v1.3.6 | v1.4.0-rc1 | -| -------------------- | ------- | ---------- | -| solady | 2.26 s | 2.41 s | -| Uniswap-v4-core | 7.22 s | 7.71 s | -| sparkdotfi-spark-psm | 45.53 s | 50.49 s | +1. [ithacaxyz/account](https://github.com/ithacaxyz/account) -## Forge Build (No Cache) +### Foundry Versions -| Repository | v1.3.6 | v1.4.0-rc1 | -| -------------------- | ------- | ---------- | -| ithacaxyz-account | 9.16 s | 9.08 s | -| solady | 14.62 s | 14.69 s | -| Uniswap-v4-core | 2m 3.8s | 2m 5.3s | -| sparkdotfi-spark-psm | 13.17 s | 13.14 s | +- **stable**: forge Version: 1.5.0-dev (6e718be 2025-12-07) +- **nightly**: forge Version: 1.5.0-dev (6e718be 2025-12-07) ## Forge Build (With Cache) -| Repository | v1.3.6 | v1.4.0-rc1 | -| -------------------- | ------- | ---------- | -| ithacaxyz-account | 0.156 s | 0.113 s | -| solady | 0.089 s | 0.094 s | -| Uniswap-v4-core | 0.133 s | 0.127 s | -| sparkdotfi-spark-psm | 0.173 s | 0.131 s | - -## Forge Coverage - -| Repository | v1.3.6 | v1.4.0-rc1 | -| -------------------- | -------- | ---------- | -| ithacaxyz-account | 14.91 s | 13.34 s | -| Uniswap-v4-core | 1m 34.8s | 1m 30.3s | -| sparkdotfi-spark-psm | 3m 49.3s | 3m 40.2s | +| Repository | stable | nightly | +|------------|----------|----------| +| ithacaxyz-account | 0.345 s | 0.279 s | ## System Information -- **OS**: macos +- **OS**: linux - **CPU**: 8 -- **Rustc**: rustc 1.90.0-nightly (3014e79f9 2025-07-15) +- **Rustc**: rustc 1.93.0 (254b59607 2026-01-19) diff --git a/sleep.json b/sleep.json new file mode 100644 index 0000000000000..5b430e1e663f6 --- /dev/null +++ b/sleep.json @@ -0,0 +1,955 @@ +{ + "results": [ + { + "command": "sleep 0.020", + "mean": 0.023726515413333333, + "stddev": 0.004602014051751124, + "median": 0.02267755758, + "user": 0.0013185473333333334, + "system": 0.0020899164444444446, + "min": 0.02109890308, + "max": 0.05602819808, + "times": [ + 0.02856005608, + 0.02346135008, + 0.02202502208, + 0.02139558708, + 0.02265920408, + 0.02121691608, + 0.02272505608, + 0.02114247908, + 0.02157142808, + 0.021514666079999998, + 0.02161920108, + 0.02335035008, + 0.02224331408, + 0.02228639708, + 0.02152537208, + 0.021732302079999998, + 0.02273370308, + 0.02115513608, + 0.02268494308, + 0.02244547308, + 0.023943647079999998, + 0.02324528508, + 0.02152617908, + 0.023991903079999998, + 0.02250884108, + 0.02342551708, + 0.02113216608, + 0.02168223108, + 0.02222267508, + 0.02273532108, + 0.02273995308, + 0.05602819808, + 0.02501500608, + 0.03121396008, + 0.02424400108, + 0.02459129108, + 0.02633760708, + 0.02377406808, + 0.02365474708, + 0.02406064008, + 0.02300910408, + 0.02437339208, + 0.02317403908, + 0.02257532008, + 0.02267017208, + 0.02356714508, + 0.02367204808, + 0.02258227108, + 0.02330384008, + 0.02225645108, + 0.02478414908, + 0.02484724308, + 0.02270765708, + 0.02339114708, + 0.02450795908, + 0.02348840008, + 0.044674490080000004, + 0.028041754080000002, + 0.022940745079999998, + 0.02259975308, + 0.022112378079999998, + 0.02271348408, + 0.02320266708, + 0.02284982108, + 0.02244050908, + 0.02238655808, + 0.022084648079999998, + 0.02241669808, + 0.02523103408, + 0.02256237908, + 0.03532525108, + 0.02232798408, + 0.02173793008, + 0.021903001079999998, + 0.02288046308, + 0.02368652508, + 0.02211418708, + 0.02265551308, + 0.02187778308, + 0.02191395108, + 0.02182523808, + 0.02185612208, + 0.02109890308, + 0.02294132008, + 0.02191512608, + 0.02264461208, + 0.02227651108, + 0.02307147508, + 0.02227169708, + 0.02177434208 + ], + "memory_usage_byte": [ + 3014656, + 3014656, + 3014656, + 3014656, + 3014656, + 3014656, + 3014656, + 3014656, + 3014656, + 3014656, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3268608, + 3268608, + 3268608, + 3268608, + 3268608, + 3268608, + 3268608, + 3268608, + 3268608, + 3268608, + 3268608, + 3268608, + 3268608, + 3268608, + 3268608, + 3268608, + 3268608, + 3268608, + 3268608, + 3268608, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680 + ], + "exit_codes": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + }, + { + "command": "sleep 0.021", + "mean": 0.022889189941111117, + "stddev": 0.0007161191938371117, + "median": 0.02280623708, + "user": 0.0009166992592592593, + "system": 0.0016941181481481477, + "min": 0.02132554808, + "max": 0.02453766808, + "times": [ + 0.02311599608, + 0.02274468508, + 0.02193879008, + 0.02158843608, + 0.02329398008, + 0.02379494508, + 0.02260801308, + 0.02439507908, + 0.02448522508, + 0.02403379508, + 0.02298143008, + 0.02263027308, + 0.02229235308, + 0.02335063508, + 0.02377098008, + 0.02269184108, + 0.023631199079999998, + 0.02338021508, + 0.02198521708, + 0.02251586208, + 0.022295963079999998, + 0.02226397608, + 0.02453766808, + 0.02184453408, + 0.02289659908, + 0.02382663208, + 0.02347397108, + 0.02225926308, + 0.02207640608, + 0.02243237108, + 0.02278192608, + 0.02270514808, + 0.02245069008, + 0.023018867079999998, + 0.02399866208, + 0.02236840708, + 0.02366382208, + 0.02294188908, + 0.02155127708, + 0.02294999808, + 0.02132554808, + 0.02242025908, + 0.02202766108, + 0.02182175108, + 0.02272186608, + 0.02211805308, + 0.02319764908, + 0.022308045079999998, + 0.02345400908, + 0.022437877079999998, + 0.02273417808, + 0.02217370908, + 0.02254318408, + 0.023269922079999998, + 0.02384951108, + 0.02419476108, + 0.02439866908, + 0.02354840508, + 0.02304219108, + 0.02354960608, + 0.02382648708, + 0.02345751208, + 0.02367913708, + 0.02253067208, + 0.02215132608, + 0.022603942079999998, + 0.02284062808, + 0.02252907808, + 0.02220393508, + 0.023291509079999998, + 0.02399456908, + 0.02407123208, + 0.02279175108, + 0.02300624708, + 0.02309500408, + 0.023036532079999998, + 0.02303833108, + 0.02316846908, + 0.02228349608, + 0.02247140608, + 0.022482600079999998, + 0.02370720808, + 0.02220123708, + 0.02230588608, + 0.02333678708, + 0.02153336008, + 0.02203071908, + 0.02279195108, + 0.02353659108, + 0.02267460708, + 0.022536274079999998, + 0.022769262079999998, + 0.02314857808, + 0.02194885908, + 0.02355038408, + 0.02320035308, + 0.02307451408, + 0.02379926408, + 0.02330480208, + 0.02257055708, + 0.02330320308, + 0.02303003208, + 0.02327859908, + 0.02171311608, + 0.02282052308, + 0.02170123708, + 0.02254831308, + 0.02235855408 + ], + "memory_usage_byte": [ + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680 + ], + "exit_codes": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + }, + { + "command": "sleep 0.022", + "mean": 0.02415569324504855, + "stddev": 0.0009830972994273135, + "median": 0.02409406108, + "user": 0.001165289514563107, + "system": 0.001767603883495146, + "min": 0.02243173808, + "max": 0.02755932908, + "times": [ + 0.02456728108, + 0.02650439708, + 0.02480475408, + 0.02452974808, + 0.02300978308, + 0.02521451608, + 0.02543841408, + 0.02538411108, + 0.02475773908, + 0.02403843308, + 0.02426362708, + 0.02326921708, + 0.02447185308, + 0.02361749008, + 0.02410661008, + 0.02371481508, + 0.02327300908, + 0.02430165908, + 0.02328269108, + 0.02315262608, + 0.02380195808, + 0.02283639508, + 0.02491355808, + 0.02401717008, + 0.02556049408, + 0.02350359508, + 0.02400529208, + 0.02533555808, + 0.02467923308, + 0.02478442308, + 0.02422068708, + 0.02352175108, + 0.02481882108, + 0.02456148108, + 0.02314905108, + 0.024188183079999998, + 0.02483985908, + 0.02289141308, + 0.02364977308, + 0.02354907008, + 0.02379135508, + 0.026812933079999997, + 0.023360627079999998, + 0.02331436308, + 0.02504176308, + 0.02358805508, + 0.02409406108, + 0.02350689508, + 0.02303628508, + 0.02430972408, + 0.02516170908, + 0.02352843108, + 0.02274564308, + 0.02345165808, + 0.02429327308, + 0.02252948108, + 0.02445868508, + 0.02755932908, + 0.02522621808, + 0.02491753008, + 0.022858510079999998, + 0.02401968108, + 0.02409596908, + 0.02390450108, + 0.02373108808, + 0.027211489079999998, + 0.02537487108, + 0.02319182608, + 0.02390569508, + 0.02490164708, + 0.02384732708, + 0.02243173808, + 0.02367003008, + 0.02494288308, + 0.02436298308, + 0.02390639308, + 0.02423030808, + 0.02430082908, + 0.02320845908, + 0.02421546708, + 0.02530823508, + 0.02368935308, + 0.02306283708, + 0.023536658079999998, + 0.02359881208, + 0.02438320308, + 0.02477724008, + 0.02362231908, + 0.02419465008, + 0.02596891608, + 0.02307578608, + 0.02459456508, + 0.02384055408, + 0.02421387408, + 0.02510733208, + 0.02473580508, + 0.02243970708, + 0.02253156008, + 0.02550018108, + 0.02440877608, + 0.02281331608, + 0.02354148408, + 0.02352098308 + ], + "memory_usage_byte": [ + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680 + ], + "exit_codes": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + } + ] +} From e0b64ca9f339c880a88c1c7e0a4b49597c67a77e Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Wed, 28 Jan 2026 11:16:04 +0700 Subject: [PATCH 206/232] Update benches/LATEST.md Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- benches/LATEST.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/benches/LATEST.md b/benches/LATEST.md index 2ddf3b8c922f1..00776abc94003 100644 --- a/benches/LATEST.md +++ b/benches/LATEST.md @@ -4,7 +4,7 @@ ## Summary -Benchmarked 2 Foundry versions across 1 repositories. +Benchmarked 2 Foundry versions across 1 repository. ### Repositories Tested From 4d4b5fc510a0631104062ca0efe18630a0851558 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Wed, 28 Jan 2026 12:02:39 +0700 Subject: [PATCH 207/232] Potential fix for code scanning alert no. 102: Artifact poisoning (#351) Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> --- .github/workflows/npm.yml | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/.github/workflows/npm.yml b/.github/workflows/npm.yml index 6ef9898e62587..3bfadac860785 100644 --- a/.github/workflows/npm.yml +++ b/.github/workflows/npm.yml @@ -164,15 +164,29 @@ jobs: # Derive RELEASE_VERSION from any foundry artifact we downloaded # Expected names: foundry___.{tar.gz,zip} - first_file=$(ls "$ARTIFACT_DIR"/foundry_* 2>/dev/null | head -n1 || true) - if [[ -z "${first_file}" ]]; then - echo "No foundry artifacts found to publish" >&2 + shopt -s nullglob + foundry_files=("$ARTIFACT_DIR"/foundry_*) + shopt -u nullglob + + if [[ ${#foundry_files[@]} -eq 0 ]]; then + echo "No foundry artifacts found to publish in $ARTIFACT_DIR" >&2 exit 1 fi + + first_file="${foundry_files[0]}" version_part=$(basename "$first_file") version_part=${version_part#foundry_} - export RELEASE_VERSION=${version_part%%_*} - echo "Detected RELEASE_VERSION=$RELEASE_VERSION" + RELEASE_VERSION=${version_part%%_*} + + # Validate derived RELEASE_VERSION to mitigate artifact poisoning + # Require a sane version format, e.g. 1.2.3 or 1.2.3-beta.1 + if [[ ! "$RELEASE_VERSION" =~ ^[0-9]+(\.[0-9]+)*(-[0-9A-Za-z.-]+)?$ ]]; then + echo "ERROR: Derived RELEASE_VERSION '$RELEASE_VERSION' from artifact '$first_file' is not a valid version" >&2 + exit 1 + fi + + export RELEASE_VERSION + echo "Detected RELEASE_VERSION=$RELEASE_VERSION from artifact $first_file" printf 'RELEASE_VERSION=%s\n' "$RELEASE_VERSION" >>"$GITHUB_OUTPUT" From 71a26eea6cce80052b3a82da9aa7c9aa0d987b09 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Wed, 28 Jan 2026 12:04:35 +0700 Subject: [PATCH 208/232] benches\LATEST.md (#350) * benches\LATEST.md * Update benches/LATEST.md Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --------- Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> --- benches/LATEST.md | 71 +--- sleep.json | 955 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 968 insertions(+), 58 deletions(-) create mode 100644 sleep.json diff --git a/benches/LATEST.md b/benches/LATEST.md index 7ea1049a2ac41..00776abc94003 100644 --- a/benches/LATEST.md +++ b/benches/LATEST.md @@ -1,73 +1,28 @@ # Foundry Benchmark Results -**Date**: 2025-10-02 12:14:23 +**Date**: 2026-01-27 03:38:34 -## Repositories Tested +## Summary -1. [ithacaxyz/account](https://github.com/ithacaxyz/account) -2. [Vectorized/solady](https://github.com/Vectorized/solady) -3. [Uniswap/v4-core](https://github.com/Uniswap/v4-core) -4. [sparkdotfi/spark-psm](https://github.com/sparkdotfi/spark-psm) - -## Foundry Versions - -- **v1.3.6**: forge Version: 1.3.6-v1.3.6 (d241588 2025-09-16) -- **v1.4.0-rc1**: forge Version: 1.4.0-v1.4.0-rc1 (bd0e4a7 2025-10-01) - -## Forge Test - -| Repository | v1.3.6 | v1.4.0-rc1 | -| -------------------- | ------- | ---------- | -| ithacaxyz-account | 3.17 s | 2.94 s | -| solady | 2.28 s | 2.10 s | -| Uniswap-v4-core | 7.27 s | 6.13 s | -| sparkdotfi-spark-psm | 43.04 s | 44.08 s | +Benchmarked 2 Foundry versions across 1 repository. -## Forge Fuzz Test +### Repositories Tested -| Repository | v1.3.6 | v1.4.0-rc1 | -| -------------------- | ------ | ---------- | -| ithacaxyz-account | 3.18 s | 3.02 s | -| solady | 2.39 s | 2.24 s | -| Uniswap-v4-core | 6.84 s | 6.20 s | -| sparkdotfi-spark-psm | 3.07 s | 2.72 s | - -## Forge Test (Isolated) - -| Repository | v1.3.6 | v1.4.0-rc1 | -| -------------------- | ------- | ---------- | -| solady | 2.26 s | 2.41 s | -| Uniswap-v4-core | 7.22 s | 7.71 s | -| sparkdotfi-spark-psm | 45.53 s | 50.49 s | +1. [ithacaxyz/account](https://github.com/ithacaxyz/account) -## Forge Build (No Cache) +### Foundry Versions -| Repository | v1.3.6 | v1.4.0-rc1 | -| -------------------- | ------- | ---------- | -| ithacaxyz-account | 9.16 s | 9.08 s | -| solady | 14.62 s | 14.69 s | -| Uniswap-v4-core | 2m 3.8s | 2m 5.3s | -| sparkdotfi-spark-psm | 13.17 s | 13.14 s | +- **stable**: forge Version: 1.5.0-dev (6e718be 2025-12-07) +- **nightly**: forge Version: 1.5.0-dev (6e718be 2025-12-07) ## Forge Build (With Cache) -| Repository | v1.3.6 | v1.4.0-rc1 | -| -------------------- | ------- | ---------- | -| ithacaxyz-account | 0.156 s | 0.113 s | -| solady | 0.089 s | 0.094 s | -| Uniswap-v4-core | 0.133 s | 0.127 s | -| sparkdotfi-spark-psm | 0.173 s | 0.131 s | - -## Forge Coverage - -| Repository | v1.3.6 | v1.4.0-rc1 | -| -------------------- | -------- | ---------- | -| ithacaxyz-account | 14.91 s | 13.34 s | -| Uniswap-v4-core | 1m 34.8s | 1m 30.3s | -| sparkdotfi-spark-psm | 3m 49.3s | 3m 40.2s | +| Repository | stable | nightly | +|------------|----------|----------| +| ithacaxyz-account | 0.345 s | 0.279 s | ## System Information -- **OS**: macos +- **OS**: linux - **CPU**: 8 -- **Rustc**: rustc 1.90.0-nightly (3014e79f9 2025-07-15) +- **Rustc**: rustc 1.93.0 (254b59607 2026-01-19) diff --git a/sleep.json b/sleep.json new file mode 100644 index 0000000000000..5b430e1e663f6 --- /dev/null +++ b/sleep.json @@ -0,0 +1,955 @@ +{ + "results": [ + { + "command": "sleep 0.020", + "mean": 0.023726515413333333, + "stddev": 0.004602014051751124, + "median": 0.02267755758, + "user": 0.0013185473333333334, + "system": 0.0020899164444444446, + "min": 0.02109890308, + "max": 0.05602819808, + "times": [ + 0.02856005608, + 0.02346135008, + 0.02202502208, + 0.02139558708, + 0.02265920408, + 0.02121691608, + 0.02272505608, + 0.02114247908, + 0.02157142808, + 0.021514666079999998, + 0.02161920108, + 0.02335035008, + 0.02224331408, + 0.02228639708, + 0.02152537208, + 0.021732302079999998, + 0.02273370308, + 0.02115513608, + 0.02268494308, + 0.02244547308, + 0.023943647079999998, + 0.02324528508, + 0.02152617908, + 0.023991903079999998, + 0.02250884108, + 0.02342551708, + 0.02113216608, + 0.02168223108, + 0.02222267508, + 0.02273532108, + 0.02273995308, + 0.05602819808, + 0.02501500608, + 0.03121396008, + 0.02424400108, + 0.02459129108, + 0.02633760708, + 0.02377406808, + 0.02365474708, + 0.02406064008, + 0.02300910408, + 0.02437339208, + 0.02317403908, + 0.02257532008, + 0.02267017208, + 0.02356714508, + 0.02367204808, + 0.02258227108, + 0.02330384008, + 0.02225645108, + 0.02478414908, + 0.02484724308, + 0.02270765708, + 0.02339114708, + 0.02450795908, + 0.02348840008, + 0.044674490080000004, + 0.028041754080000002, + 0.022940745079999998, + 0.02259975308, + 0.022112378079999998, + 0.02271348408, + 0.02320266708, + 0.02284982108, + 0.02244050908, + 0.02238655808, + 0.022084648079999998, + 0.02241669808, + 0.02523103408, + 0.02256237908, + 0.03532525108, + 0.02232798408, + 0.02173793008, + 0.021903001079999998, + 0.02288046308, + 0.02368652508, + 0.02211418708, + 0.02265551308, + 0.02187778308, + 0.02191395108, + 0.02182523808, + 0.02185612208, + 0.02109890308, + 0.02294132008, + 0.02191512608, + 0.02264461208, + 0.02227651108, + 0.02307147508, + 0.02227169708, + 0.02177434208 + ], + "memory_usage_byte": [ + 3014656, + 3014656, + 3014656, + 3014656, + 3014656, + 3014656, + 3014656, + 3014656, + 3014656, + 3014656, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3141632, + 3268608, + 3268608, + 3268608, + 3268608, + 3268608, + 3268608, + 3268608, + 3268608, + 3268608, + 3268608, + 3268608, + 3268608, + 3268608, + 3268608, + 3268608, + 3268608, + 3268608, + 3268608, + 3268608, + 3268608, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680 + ], + "exit_codes": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + }, + { + "command": "sleep 0.021", + "mean": 0.022889189941111117, + "stddev": 0.0007161191938371117, + "median": 0.02280623708, + "user": 0.0009166992592592593, + "system": 0.0016941181481481477, + "min": 0.02132554808, + "max": 0.02453766808, + "times": [ + 0.02311599608, + 0.02274468508, + 0.02193879008, + 0.02158843608, + 0.02329398008, + 0.02379494508, + 0.02260801308, + 0.02439507908, + 0.02448522508, + 0.02403379508, + 0.02298143008, + 0.02263027308, + 0.02229235308, + 0.02335063508, + 0.02377098008, + 0.02269184108, + 0.023631199079999998, + 0.02338021508, + 0.02198521708, + 0.02251586208, + 0.022295963079999998, + 0.02226397608, + 0.02453766808, + 0.02184453408, + 0.02289659908, + 0.02382663208, + 0.02347397108, + 0.02225926308, + 0.02207640608, + 0.02243237108, + 0.02278192608, + 0.02270514808, + 0.02245069008, + 0.023018867079999998, + 0.02399866208, + 0.02236840708, + 0.02366382208, + 0.02294188908, + 0.02155127708, + 0.02294999808, + 0.02132554808, + 0.02242025908, + 0.02202766108, + 0.02182175108, + 0.02272186608, + 0.02211805308, + 0.02319764908, + 0.022308045079999998, + 0.02345400908, + 0.022437877079999998, + 0.02273417808, + 0.02217370908, + 0.02254318408, + 0.023269922079999998, + 0.02384951108, + 0.02419476108, + 0.02439866908, + 0.02354840508, + 0.02304219108, + 0.02354960608, + 0.02382648708, + 0.02345751208, + 0.02367913708, + 0.02253067208, + 0.02215132608, + 0.022603942079999998, + 0.02284062808, + 0.02252907808, + 0.02220393508, + 0.023291509079999998, + 0.02399456908, + 0.02407123208, + 0.02279175108, + 0.02300624708, + 0.02309500408, + 0.023036532079999998, + 0.02303833108, + 0.02316846908, + 0.02228349608, + 0.02247140608, + 0.022482600079999998, + 0.02370720808, + 0.02220123708, + 0.02230588608, + 0.02333678708, + 0.02153336008, + 0.02203071908, + 0.02279195108, + 0.02353659108, + 0.02267460708, + 0.022536274079999998, + 0.022769262079999998, + 0.02314857808, + 0.02194885908, + 0.02355038408, + 0.02320035308, + 0.02307451408, + 0.02379926408, + 0.02330480208, + 0.02257055708, + 0.02330320308, + 0.02303003208, + 0.02327859908, + 0.02171311608, + 0.02282052308, + 0.02170123708, + 0.02254831308, + 0.02235855408 + ], + "memory_usage_byte": [ + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680 + ], + "exit_codes": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + }, + { + "command": "sleep 0.022", + "mean": 0.02415569324504855, + "stddev": 0.0009830972994273135, + "median": 0.02409406108, + "user": 0.001165289514563107, + "system": 0.001767603883495146, + "min": 0.02243173808, + "max": 0.02755932908, + "times": [ + 0.02456728108, + 0.02650439708, + 0.02480475408, + 0.02452974808, + 0.02300978308, + 0.02521451608, + 0.02543841408, + 0.02538411108, + 0.02475773908, + 0.02403843308, + 0.02426362708, + 0.02326921708, + 0.02447185308, + 0.02361749008, + 0.02410661008, + 0.02371481508, + 0.02327300908, + 0.02430165908, + 0.02328269108, + 0.02315262608, + 0.02380195808, + 0.02283639508, + 0.02491355808, + 0.02401717008, + 0.02556049408, + 0.02350359508, + 0.02400529208, + 0.02533555808, + 0.02467923308, + 0.02478442308, + 0.02422068708, + 0.02352175108, + 0.02481882108, + 0.02456148108, + 0.02314905108, + 0.024188183079999998, + 0.02483985908, + 0.02289141308, + 0.02364977308, + 0.02354907008, + 0.02379135508, + 0.026812933079999997, + 0.023360627079999998, + 0.02331436308, + 0.02504176308, + 0.02358805508, + 0.02409406108, + 0.02350689508, + 0.02303628508, + 0.02430972408, + 0.02516170908, + 0.02352843108, + 0.02274564308, + 0.02345165808, + 0.02429327308, + 0.02252948108, + 0.02445868508, + 0.02755932908, + 0.02522621808, + 0.02491753008, + 0.022858510079999998, + 0.02401968108, + 0.02409596908, + 0.02390450108, + 0.02373108808, + 0.027211489079999998, + 0.02537487108, + 0.02319182608, + 0.02390569508, + 0.02490164708, + 0.02384732708, + 0.02243173808, + 0.02367003008, + 0.02494288308, + 0.02436298308, + 0.02390639308, + 0.02423030808, + 0.02430082908, + 0.02320845908, + 0.02421546708, + 0.02530823508, + 0.02368935308, + 0.02306283708, + 0.023536658079999998, + 0.02359881208, + 0.02438320308, + 0.02477724008, + 0.02362231908, + 0.02419465008, + 0.02596891608, + 0.02307578608, + 0.02459456508, + 0.02384055408, + 0.02421387408, + 0.02510733208, + 0.02473580508, + 0.02243970708, + 0.02253156008, + 0.02550018108, + 0.02440877608, + 0.02281331608, + 0.02354148408, + 0.02352098308 + ], + "memory_usage_byte": [ + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680, + 3399680 + ], + "exit_codes": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + } + ] +} From cc693d32a187dc57a2d405601cdcf7c9586fe23f Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Wed, 28 Jan 2026 13:35:41 +0700 Subject: [PATCH 209/232] Potential fix for code scanning alert no. 109: Uncontrolled data used in path expression Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --- crates/test-utils/src/script.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/crates/test-utils/src/script.rs b/crates/test-utils/src/script.rs index f20dae571cef3..f3adc9e7bb420 100644 --- a/crates/test-utils/src/script.rs +++ b/crates/test-utils/src/script.rs @@ -123,13 +123,21 @@ impl ScriptTester { fs::create_dir_all(&to_dir)?; for entry in fs::read_dir(&from_dir)? { let file = entry?.path(); + // Canonicalize the file path and ensure it stays within canonical_from_dir + let canonical_file = match file.canonicalize() { + Ok(path) => path, + Err(_) => continue, + }; + if !canonical_file.starts_with(&canonical_from_dir) { + continue; + } // Only operate on regular files to avoid following symlinks or directories - let metadata = fs::symlink_metadata(&file)?; + let metadata = fs::symlink_metadata(&canonical_file)?; let ftype = metadata.file_type(); if !ftype.is_file() { continue; } - let name = match file.file_name() { + let name = match canonical_file.file_name() { Some(name) => name, None => continue, }; @@ -139,15 +147,7 @@ impl ScriptTester { // Skip invalid (potentially dangerous) file names continue; } - // Verify canonicalized file is in canonical_from_dir to avoid symlink traversal - if let Ok(canonical_file) = file.canonicalize() { - if !canonical_file.starts_with(&canonical_from_dir) { - continue; - } - } else { - continue; - } - fs::copy(&file, to_dir.join(name))?; + fs::copy(&canonical_file, to_dir.join(name))?; } Ok(()) } From 76bba522f0409013e1e868a7c13b7dd4a533156d Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Wed, 28 Jan 2026 14:43:24 +0700 Subject: [PATCH 210/232] Wagmi (e604566) (#344) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore(deps): bump revm to 24.0.0 (#10601) * feat: implement add_balance endpoint (#10636) * fix(bindings): ensure forge bind generates snake_case file names (#10622) * fix(bindings): ensure forge bind generates snake_case file names * refactor: use heck crate for snake_case conversion --------- Co-authored-by: zerosnacks <95942363+zerosnacks@users.noreply.github.com> * chore: standardize lint help + validate docs existance (#10639) * feat(cast mktx): add support for "--ethsign" option (#10641) - Sign transactions using "eth_signTransaction" on local node with unlocked accounts. - Same TX building logic as in "cast send --unlocked". - Added a test case to validate the new functionality. * chore(wallets): improve error message for signer instantiation failure (#10646) chore(wallets): improve error message on signer instantiation failure * chore: replaced anvil hardforks with alloy hardforks (#10612) * chore: replaced anvil hardforks with alloy hardforks * fixes * fixes * fixes * removed redundant op and alloy hardforks enum * fixes * fixes * bumped alloy hardforks and kept default to prague and isthmus * bumped alloy-hardforks and fixes --------- Co-authored-by: zerosnacks <95942363+zerosnacks@users.noreply.github.com> * fix(`anvil`): latest evm version should be prague (#10653) * fix(`anvil`): latest evm version should be prague * fix test * nit * chore(deps): bump tracing-subscriber (#51) Bumps the cargo group with 1 update in the / directory: [tracing-subscriber](https://github.com/tokio-rs/tracing). Updates `tracing-subscriber` from 0.3.19 to 0.3.20 - [Release notes](https://github.com/tokio-rs/tracing/releases) - [Commits](https://github.com/tokio-rs/tracing/compare/tracing-subscriber-0.3.19...tracing-subscriber-0.3.20) --- updated-dependencies: - dependency-name: tracing-subscriber dependency-version: 0.3.20 dependency-type: direct:production dependency-group: cargo ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Update test.yml (#52) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Update docker-image.yml (#53) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Create ci.yml (#57) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Create ci_cargo.yml (#59) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Create web3_defi_gamefi.yml (#61) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Update ci.yml (#66) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Create config.yml (#71) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Update dependencies.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 21: Workflow does not contain permissions Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Create ci_cargo.yml (#72) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Create config.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 2: Workflow does not contain permissions Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Update crates/common/src/contracts.rs Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Update ci.yml (#107) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Create config.yml (#114) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * chore(deps): bump github/codeql-action from 3 to 4 (#113) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3 to 4. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/v3...v4) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: '4' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump DeterminateSystems/determinate-nix-action (#111) Bumps [DeterminateSystems/determinate-nix-action](https://github.com/determinatesystems/determinate-nix-action) from 3.11.2 to 3.11.3. - [Release notes](https://github.com/determinatesystems/determinate-nix-action/releases) - [Commits](https://github.com/determinatesystems/determinate-nix-action/compare/dbda91f6efef3ee627f56175120aa9543687d830...762d7fdba79d046449732c729c1d3aaad021baa2) --- updated-dependencies: - dependency-name: DeterminateSystems/determinate-nix-action dependency-version: 3.11.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump crate-ci/typos from 1.38.0 to 1.38.1 (#112) Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.38.0 to 1.38.1. - [Release notes](https://github.com/crate-ci/typos/releases) - [Changelog](https://github.com/crate-ci/typos/blob/master/CHANGELOG.md) - [Commits](https://github.com/crate-ci/typos/compare/83157de2df0fa7c7ae20f73f9dbed44c41f2bb64...80c8a4945eec0f6d464eaf9e65ed98ef085283d1) --- updated-dependencies: - dependency-name: crate-ci/typos dependency-version: 1.38.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump softprops/action-gh-release from 2.3.4 to 2.4.1 (#110) Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 2.3.4 to 2.4.1. - [Release notes](https://github.com/softprops/action-gh-release/releases) - [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md) - [Commits](https://github.com/softprops/action-gh-release/compare/62c96d0c4e8a889135c1f3a25910db8dbe0e85f7...6da8fa9354ddfdc4aeace5fc48d7f679b5214090) --- updated-dependencies: - dependency-name: softprops/action-gh-release dependency-version: 2.4.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump taiki-e/install-action from 2.62.21 to 2.62.28 (#109) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.62.21 to 2.62.28. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/522492a8c115f1b6d4d318581f09638e9442547b...e7ef886cf8f69c25ecef6bbc2858a42e273496ec) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-version: 2.62.28 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Update test.yml (#115) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Update crates/doc/src/writer/buf_writer.rs Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Update config.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Update and rename config.yml to ci.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Rename ci_cargo.yml to ci_v1.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Update .circleci/ci_v1.yml Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Foundry/master (#122) * Create ci_cargo.yml (#72) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Create config.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Update and rename config.yml to ci.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Rename ci_cargo.yml to ci_v1.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Update .circleci/ci_v1.yml Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --------- Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> * Update and rename config.yml to ci_deploy.yml (#123) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Create snyk-container.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Update and rename ci.yml to ci-say-hello.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Update test.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Create config.ym (#128) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * chore(deps): bump alloy-dyn-abi in the cargo group across 1 directory (#129) Bumps the cargo group with 1 update in the / directory: [alloy-dyn-abi](https://github.com/alloy-rs/core). Updates `alloy-dyn-abi` from 1.4.0 to 1.4.1 - [Release notes](https://github.com/alloy-rs/core/releases) - [Changelog](https://github.com/alloy-rs/core/blob/main/CHANGELOG.md) - [Commits](https://github.com/alloy-rs/core/compare/v1.4.0...v1.4.1) --- updated-dependencies: - dependency-name: alloy-dyn-abi dependency-version: 1.4.1 dependency-type: direct:production dependency-group: cargo ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Create cargo.yml (#74) (#130) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Fix typo in CircleCI config file name Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Update .circleci/config.yml Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Fix formatting in cargo.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Fix indentation for on_fail condition in CI config Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Fix indentation in CircleCI configuration Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * chore(deps): bump taiki-e/install-action from 2.62.21 to 2.62.31 (#139) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.62.21 to 2.62.31. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/v2.62.21...0005e0116e92d8489d8d96fbff83f061c79ba95a) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-version: 2.62.31 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump github/codeql-action from 3 to 4 (#138) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3 to 4. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/v3...v4) --- updated-dependencies: - dependency-name: github/codeql-action dependency-version: '4' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump snyk/actions Bumps [snyk/actions](https://github.com/snyk/actions) from 14818c4695ecc4045f33c9cee9e795a788711ca4 to 9adf32b1121593767fc3c057af55b55db032dc04. - [Release notes](https://github.com/snyk/actions/releases) - [Commits](https://github.com/snyk/actions/compare/14818c4695ecc4045f33c9cee9e795a788711ca4...9adf32b1121593767fc3c057af55b55db032dc04) --- updated-dependencies: - dependency-name: snyk/actions dependency-version: 9adf32b1121593767fc3c057af55b55db032dc04 dependency-type: direct:production ... Signed-off-by: dependabot[bot] * Update CircleCI config with comments and formatting Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Update config.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Update and rename ci-say-hello.yml to ci-web3-defi-gamefi.yml (#154) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Delete .circleci/ci-web3-defi-gamefi.yml (#155) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Delete .circleci/ci_deploy.yml (#158) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Delete .circleci/cargo.yml (#159) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * chore(deps): bump taiki-e/install-action from 2.62.31 to 2.62.33 (#162) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.62.31 to 2.62.33. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/0005e0116e92d8489d8d96fbff83f061c79ba95a...e43a5023a747770bfcb71ae048541a681714b951) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-version: 2.62.33 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump actions/checkout from 4 to 5 (#163) Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Merge branch 'foundry-rs:master' (#164) * Create ci_cargo.yml (#72) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Create config.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Rename ci_cargo.yml to cargo.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * fix(fmt): handle trailing coments between base contracts (#12127) * fix(fmt): account for ternary operators when estimating size * fix(fmt): handle comments between inherited base contracts * test: layout + base inheritance * feat(forge): add bypass prevrandao (#12125) * feat(forge): add bypass prevrandao * Update crates/evm/networks/src/lib.rs Co-authored-by: 0xrusowsky <90208954+0xrusowsky@users.noreply.github.com> * changes after review: remove duped code --------- Co-authored-by: 0xrusowsky <90208954+0xrusowsky@users.noreply.github.com> * fix(fmt): filter libs when recursing (#12119) * fix(fmt): account for ternary operators when estimating size * fix(fmt): filter libs when recursing * style: clippy * test: wipe contracts before formatting * test: explicitly test ignore * fix(fmt): break try stmts in a fn header-like fashion (#12131) * chore(deps): bump softprops/action-gh-release from 2.3.4 to 2.4.1 Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 2.3.4 to 2.4.1. - [Release notes](https://github.com/softprops/action-gh-release/releases) - [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md) - [Commits](https://github.com/softprops/action-gh-release/compare/62c96d0c4e8a889135c1f3a25910db8dbe0e85f7...6da8fa9354ddfdc4aeace5fc48d7f679b5214090) --- updated-dependencies: - dependency-name: softprops/action-gh-release dependency-version: 2.4.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * chore(deps): bump taiki-e/install-action from 2.62.28 to 2.62.33 (#161) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.62.28 to 2.62.33. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/e7ef886cf8f69c25ecef6bbc2858a42e273496ec...e43a5023a747770bfcb71ae048541a681714b951) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-version: 2.62.33 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --------- Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Signed-off-by: dependabot[bot] Co-authored-by: 0xrusowsky <90208954+0xrusowsky@users.noreply.github.com> Co-authored-by: grandizzy <38490174+grandizzy@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * fix(anvil): always disable nonce check (foundry-rs#12144) (#165) * test: refactor testdata/ tests to be run in `forge test` (#12049) * test: run forge test on testdata/ * chore: refactor to use common Test contract * chore: disable testGasMeteringExternal, via-ir * test: rm unused repros * fix: paths * upd * fmt * fix more tests * test: turn testNonExistingContractRevert into expectRevert * fix some more paths * legacy assertions * compile paris with paris * fix: set configs for fs tests * fix remaining paths in cheats * restrict fs permissions * fix: set runtime evm_version too * fix vyper * fix: a couple of repros * fix: we have storage layouts * fix: 3223, 3674: set sender * reorder * feat: move repros expected failures to snapshots * feat: migrate remaining repros tests * feat: rm migrated files * skip testRevertIfGetUnlinked * move expected core/ failures * upd * move logs/ * move all forgetest tests from it/ to cli/ * fix fork test * move trace/ * tmp: move fuzz/invariant out of fuzz/ * move fuzz/ * forge fmt * wips * fix: both vyper and paris; set src/ * canon * lib log * logs * Revert "fix: set runtime evm_version too" This reverts commit 7ca544b10047f608d57c74fb3500a5fbe7e2650e. Contract-level inline config will set evm version for libraries too, which means we fail on deploying libraries that are compiled with newer evm version. * fix: set evm version where needed, per test function * test: reduce gas wastage * chore: clippy * invariant mod.rs * test: fix linking tests with new utils * redact_with * Revert "wips" This reverts commit ee2c17a3023ca7ce8e7effccf0ea0a0f28f6e510. * migrate invariant/target{,Abi} * migrate InvariantAfterInvariant.t.sol * migrate InvariantAssume.t.sol * migrate InvariantCalldataDictionary.t.sol, more test utils * migrate InvariantCustomError.t.sol * migrate InvariantExcludedSenders.t.sol * migrate InvariantFixtures.t.sol * migrate InvariantHandlerFailure.t.sol * interlude: forgot to use a new file * migrate InvariantInnerContract.t.sol * migrate InvariantPreserveState.t.sol * migrate InvariantReentrancy.t.sol * migrate InvariantRollFork.t.sol * migrate InvariantScrapeValues.t.sol * migrate InvariantSequenceNoReverts.t.sol * migrate InvariantShrinkBigSequence.t.sol * migrate InvariantShrinkFailOnRevert.t.sol * migrate InvariantShrinkWithAssert.t.sol * migrate InvariantTest1.t.sol * fix InvariantInnerContract.t.sol * update new Rlp test * com * better com * nuke tests/it * test: fix testdata paths in script tester * test: fix relative paths in test_cmd * test: redact more in issue_2851 * fix: copy testdata correctly * trace addrs * manual retry logic with --retry * fix nondeterministic output * debug: fs lock error context * test: fix project root for windows * test: skip project root test if unset * normalize both * typo * Revert "typo" This reverts commit 402bea105c6f38b82664b50ca854f95e456df795. * Revert "debug: fs lock error context" This reverts commit e5caeddd1e4cb457d7b24d7d7fdfdb370e2feabf. * fix * fix: locked_write_line for windows * chore: clippy * fmt * chore: speed up fuzzed_selected_targets * other way * fix nondeterministic output 2 * fix: disable persistence * test: revert old via-ir * ci: tweak cache key * do not run trace test when isolate --------- Co-authored-by: grandizzy * fix(anvil): always disable nonce check (#12144) * deps: bump deps (#12149) * deps: bump deps 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude * minimum Cargo.lock --------- Co-authored-by: rplusq Co-authored-by: Claude Co-authored-by: DaniPopes <57450786+DaniPopes@users.noreply.github.com> --------- Co-authored-by: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Co-authored-by: grandizzy Co-authored-by: grandizzy <38490174+grandizzy@users.noreply.github.com> Co-authored-by: Rafael Quintero <32346241+rplusq@users.noreply.github.com> Co-authored-by: rplusq Co-authored-by: Claude * Update test.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Update test.yml (#167) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Update test.yml (#168) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Delete .circleci/ci.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Update cargo.yml (#171) CI/CD Configuration Update: The CircleCI configuration file, cargo.yml, has been updated to use a newer version of the Rust Docker image. Rust Toolchain Version Bump: The cimg/rust Docker image version has been incremented from 1.88.0 to 1.89.0, ensuring the CI pipeline utilizes a more recent Rust toolchain. Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Delete .circleci/ci_v1.yml (#173) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Update cargo.yml (#174) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * chore(deps): bump taiki-e/install-action from 2.62.28 to 2.62.33 (#175) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.62.28 to 2.62.33. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/v2.62.28...e43a5023a747770bfcb71ae048541a681714b951) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-version: 2.62.33 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Delete .circleci/cargo.yml (#179) I Configuration Removal: The .circleci/cargo.yml file, which defined CircleCI jobs for building and testing Rust projects, has been completely removed from the repository. Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Delete .circleci/ci_v1.yml (#182) Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update config.yml (#183) Configuration File Cleanup: Removed an unnecessary blank line in the .circleci/config.yml file, improving its formatting and readability. Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update config.yml (#187) Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Delete .circleci/config.yml Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Delete .circleci directory Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update ci_v1.yml Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update Rust Docker image version to 1.89.0 Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 76: Artifact poisoning Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * chore(deps): bump alloy-dyn-abi in the cargo group across 1 directory Bumps the cargo group with 1 update in the / directory: [alloy-dyn-abi](https://github.com/alloy-rs/core). Updates `alloy-dyn-abi` from 0.8.25 to 0.8.26 - [Release notes](https://github.com/alloy-rs/core/releases) - [Changelog](https://github.com/alloy-rs/core/blob/v0.8.26/CHANGELOG.md) - [Commits](https://github.com/alloy-rs/core/compare/v0.8.25...v0.8.26) --- updated-dependencies: - dependency-name: alloy-dyn-abi dependency-version: 0.8.26 dependency-type: direct:production dependency-group: cargo ... Signed-off-by: dependabot[bot] * Create ci-web3-gamefi.yml Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 74: Artifact poisoning Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 83: Uncontrolled data used in path expression Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 93: Uncontrolled data used in path expression Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 76: Artifact poisoning Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 94: Uncontrolled data used in path expression Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 80: Server-side request forgery Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 80: Server-side request forgery Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Create codeql.yml (#208) * Update ci.yml (#209) Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --------- https://github.com/apps/gemini-code-assist Code Review This pull request updates the Rust version in the CI from 1.88.0 to 1.89.0. While this is a good maintenance step, I've identified a potential improvement for your CI configuration. The project's Cargo.toml specifies a Minimum Supported Rust Version (MSRV) of 1.86, but the CI doesn't test against it. I've added a comment suggesting the addition of an MSRV check to prevent compatibility issues. * Update cargo.yml (#210) https://github.com/apps/gemini-code-assist ------------------- Code Review This pull request downgrades the Rust version in the CI pipeline from 1.88.0 to 1.87.0. This is inconsistent with the project's declared Minimum Supported Rust Version (MSRV) of 1.89 in Cargo.toml. My review highlights this discrepancy and suggests aligning the CI's Rust version with the MSRV to ensure the project's compatibility guarantees are properly tested. --------------- Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Foundry rs maste 1f4b36a (#214) * Create jekyll.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Create docker-image.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 58: Workflow does not contain permissions Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Update .github/workflows/docker-image.yml Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Update docker-image.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Revert "chore: fix isolate tests (#10344)" This reverts commit 70ded2b35f95ee9b4ee94f5e44961914d30a87f7. * Delete .github/workflows/jekyll.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 19: Workflow does not contain permissions Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> --------- Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> * Update and rename docker-image.yml to docker.yml (#218) Streamline the Docker CI workflow by renaming the file and enhancing it with scheduled runs, Buildx multi-platform builds, metadata tagging, conditional pushes, and automated image signing with Cosign. CI: Rename and replace the legacy docker-image.yml workflow with docker.yml Add scheduled cron runs and triggers on pushes to master, semver tags, and PRs Configure Docker Buildx for multi-platform builds with cache Extract Docker metadata and conditionally push images to GHCR on non-PR events Install Cosign and sign published Docker images using ephemeral identity tokens Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update ci.yml Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Create docker-image.yml (#224) CI: Introduce docker-image.yml GitHub Actions workflow to checkout code and build Docker image on ubuntu-latest Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update config.yml (#225) CI: Insert comment lines to delineate and structure sections in .circleci/config.yml for enhanced clarity Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update sequence.rs (#226) Enhancements: Add standalone # lines in sequence.rs to serve as hidden placeholders for rustdoc examples Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update dependencies.yml (#227) * Update dependencies.yml Refactor the weekly dependencies workflow to inline cargo update steps, auto-generate commit messages and PR bodies with update logs, and use the create-pull-request action to open update PRs on a dedicated branch. Enhancements: Define environment variables for GitHub token, branch name, PR title, and PR body including cargo update logs Inline checkout, Rust toolchain setup, and cargo update command with log cleanup instead of relying on an external workflow Craft commit messages and PR bodies dynamically by capturing and formatting cargo update output Use peter-evans/create-pull-request to push Cargo.lock updates to a 'cargo-update' branch CI: Move permissions and GitHub token configuration into the job context Explicitly set the runner to ubuntu-latest and remove the top-level empty permissions block Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update .github/workflows/dependencies.yml Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --------- Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> * Update npm.yml (#228) CI: Add comment to the Publish Binary step indicating it runs automatically after a successful release workflow or can be triggered manually with a run_id Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update snyk-container.yml (#229) Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update nextest.yml (#230) Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update const.ts (#231) Code Formatting: Removed an extraneous blank line in npm/src/const.ts to improve code cleanliness and consistency. Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Revert "Create web3_defi_gamefi.yml (#61)" (#233) This reverts commit 8575916b7675f246b54daf70cfddccb3f5b97fb0. * Create deploy.yml (#240) * Create deploy.yml CI: Add GitHub Actions workflow to build the Rust project, run tests, and build a Docker image on pushes to main/master Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 106: Workflow does not contain permissions Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --------- Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> * Update dependencies.yml Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update dependencies.yml (#247) Improve readability of the GitHub Actions dependencies workflow by adjusting whitespace and adding blank lines CI: Add blank line before the workflow name declaration Insert blank line after the scheduled cron job entry Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update dependencies.yml (#248) CI: Remove extraneous blank line in .github/workflows/dependencies.yml Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update test.yml (#249) CI: Remove dev branch from test workflow triggers Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update Cargo.lock (#253) Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update Cargo.lock (#254) Chores: Regenerate Cargo.lock to update dependencies Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Create config.yml (#255) * Create config.yml Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update .circleci/config.yml Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --------- Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> * Update config.yml (#256) Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * fix: upgrade tsdown from 0.15.12 to 0.16.1 Snyk has created this PR to upgrade tsdown from 0.15.12 to 0.16.1. See this package in npm: tsdown See this project in Snyk: https://app.snyk.io/org/dargon789/project/8da85645-409e-46fa-bd46-9b58e7905fb8?utm_source=github-cloud-app&utm_medium=referral&page=upgrade-pr * Create google.yml (#266) CI: Introduce a Google Cloud deployment workflow that builds a Docker image, pushes it to Artifact Registry, and deploys it to a GKE cluster on pushes to the main branches. Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update flake.lock (#269) Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update flake.nix (#270) Adjust Nix flake development shell configuration for better cross-platform support and simplify dependencies. Enhancements: Remove the dprint dependency from the Nix development shell. Add conditional AppKit framework linkage on Darwin systems in the Nix shell configuration. Drop custom hardeningDisable settings from the Nix development shell definition. https://github.com/apps/gemini-code-assist Code Review This pull request updates the Nix flake configuration to improve cross-platform support and simplify dependencies. The changes include removing dprint and hardeningDisable settings, and conditionally adding the AppKit framework for Darwin systems. While most changes are beneficial, removing dprint from the development shell dependencies while its configuration file remains could cause issues for contributors. I've added a comment regarding this potential inconsistency. Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update Cargo.toml (#271) Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update nextest.toml (#272) Adjust test runner configuration for nextest to better handle long-running and specific tests. Enhancements: Introduce a dedicated test group that limits chisel-serial tests to a single thread. Increase the default slow-test timeout period to reduce premature terminations for longer-running tests. Expand the slow-timeout override filter to include both ext_integration and can_test_forge_std tests. Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update dprint.json (#273) (https://github.com/apps/gemini-code-assist) Code Review This pull request updates the dprint.json configuration file. The changes correctly enable formatting for dprint.json itself by modifying the excludes list, update the JSON and Markdown dprint plugins to their latest versions, and add a final newline to the file for POSIX compliance. These are all good maintenance improvements. The changes have been reviewed and appear to be correct and beneficial. No issues were found. Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update .github/workflows/apisec-scan.yml Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update counter/README.md Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update .github/ISSUE_TEMPLATE/bug_report.md Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Dependabot/cargo/cargo 38744a1864 (#282) * chore(deps): bump alloy-dyn-abi in the cargo group across 1 directory Bumps the cargo group with 1 update in the / directory: [alloy-dyn-abi](https://github.com/alloy-rs/core). Updates `alloy-dyn-abi` from 0.8.25 to 0.8.26 - [Release notes](https://github.com/alloy-rs/core/releases) - [Changelog](https://github.com/alloy-rs/core/blob/v0.8.26/CHANGELOG.md) - [Commits](https://github.com/alloy-rs/core/compare/v0.8.25...v0.8.26) --- updated-dependencies: - dependency-name: alloy-dyn-abi dependency-version: 0.8.26 dependency-type: direct:production dependency-group: cargo ... Signed-off-by: dependabot[bot] * Update and rename ci.yml to cargo.yml (#268) Update CircleCI configuration to use a different Rust toolchain image and rename the workflow file. Build: Rename the CircleCI configuration file from ci.yml to cargo.yml. Change the CircleCI Docker image to use Rust 1.78.0 instead of 1.88.0. Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --------- Signed-off-by: dependabot[bot] Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Fix cloning of compiler settings for Vyper input Replace context.clone().compiler_settings.vyper with context.compiler_settings.vyper.clone() to avoid unnecessary cloning of the entire VerificationContext. This reduces memory allocations when creating VyperInput instances. Applied to both etherscan and sourcify verification providers. * Update config.yml (#283) Summary by Sourcery Update CircleCI pipeline to use a custom Docker executor and job tailored to the project instead of the example hello-world workflow. Enhancements: Introduce a reusable custom executor that pulls from the stable cimg/base Docker image with Docker Hub authentication. CI: Replace the sample say-hello job and workflow with a project-specific job and workflow wired to the new custom executor in .circleci/config.yml. Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * fix: use network-specific BaseFeeParams for Optimism in Anvil * Dargon789 patch 1 (#285) * Update test.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Update test.yml (#167) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Delete .circleci/ci_v1.yml (#173) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Update cargo.yml (#174) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Delete .circleci/config.yml Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 74: Artifact poisoning Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 83: Uncontrolled data used in path expression Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 93: Uncontrolled data used in path expression Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 76: Artifact poisoning Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 94: Uncontrolled data used in path expression Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 80: Server-side request forgery Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update cargo.yml (#210) https://github.com/apps/gemini-code-assist ------------------- Code Review This pull request downgrades the Rust version in the CI pipeline from 1.88.0 to 1.87.0. This is inconsistent with the project's declared Minimum Supported Rust Version (MSRV) of 1.89 in Cargo.toml. My review highlights this discrepancy and suggests aligning the CI's Rust version with the MSRV to ensure the project's compatibility guarantees are properly tested. --------------- Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Fix cloning of compiler settings for Vyper input Replace context.clone().compiler_settings.vyper with context.compiler_settings.vyper.clone() to avoid unnecessary cloning of the entire VerificationContext. This reduces memory allocations when creating VyperInput instances. Applied to both etherscan and sourcify verification providers. --------- Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Co-authored-by: Gengar * merge gh-master (#287) * Create config.yml (#236) Create .circleci/config.yml defining a version 2.1 pipeline with a docker-based "say-hello" job, checkout and echo steps, and a workflow to orchestrate it Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * fix(evm): use timestamp-based blob base fee calculation (#12959) * fix(evm): use timestamp-based blob base fee calculation * chore: use patch * Now BPO1 is default * bump to hardforks to 0.4.7 --------- Co-authored-by: Matthias Seitz * fix(config): reject bare versions in compilation restrictions (#12955) fmt Co-authored-by: tefyosL-sol * Revert "fix(config): err on unknown profile (#12946)" (#12964) This reverts commit 6ff4b52e2e572e93d0cd81591b1bd0e6ad9ed507. * Update crates/config/src/compilation.rs Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --------- Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: cakevm Co-authored-by: Matthias Seitz Co-authored-by: Theodore Solis Co-authored-by: tefyosL-sol Co-authored-by: grandizzy <38490174+grandizzy@users.noreply.github.com> Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * Foundry/ethereum ux (#284) * Potential fix for code scanning alert no. 19: Workflow does not contain permissions Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 61: Workflow does not contain permissions Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 74: Artifact poisoning Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Create config.yml (#105) * Create cargo.yml (#106) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Delete .github/workflows/docker-image.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Revert "Create cargo.yml (#106)" This reverts commit 251a2b4fce0c50e3426ffb2022d9abef5b948fa9. * Create cargo.yml (#213) https://github.com/apps/gemini-code-assist Code Review This pull request introduces a CircleCI workflow to automate formatting checks and tests. My review has identified two main issues in the configuration: redundant steps that would unnecessarily increase job execution time, and a mismatch between the Rust version in the CI environment and the one specified in the project's Cargo.toml. I've provided suggestions to fix these issues for a more efficient and consistent CI process. Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --------- Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> * Gamefi defi (#288) * chore: ignore RUSTSEC-2025-0137 (#12941) Co-authored-by: Claude * chore(deps): weekly `cargo update` (#12940) * chore(deps): weekly `cargo update` Updating git repository `https://github.com/rust-cli/rexpect` Updating git repository `https://github.com/paradigmxyz/solar.git` Skipping git submodule `https://github.com/argotorg/solidity.git` due to update strategy in .gitmodules Updating git repository `https://github.com/tempoxyz/tempo` Updating git repository `https://github.com/paradigmxyz/reth` Locking 71 packages to latest compatible versions Updating alloy-chains v0.2.23 -> v0.2.24 Updating alloy-consensus v1.1.3 -> v1.2.1 Updating alloy-consensus-any v1.1.3 -> v1.2.1 Updating alloy-contract v1.1.3 -> v1.2.1 Updating alloy-dyn-abi v1.5.1 -> v1.5.2 Updating alloy-eip5792 v1.1.3 -> v1.2.1 Updating alloy-eips v1.1.3 -> v1.2.1 Updating alloy-ens v1.1.3 -> v1.2.1 Updating alloy-genesis v1.1.3 -> v1.2.1 Updating alloy-json-abi v1.5.1 -> v1.5.2 Updating alloy-json-rpc v1.1.3 -> v1.2.1 Updating alloy-network v1.1.3 -> v1.2.1 Updating alloy-network-primitives v1.1.3 -> v1.2.1 Updating alloy-primitives v1.5.1 -> v1.5.2 Updating alloy-provider v1.1.3 -> v1.2.1 Updating alloy-pubsub v1.1.3 -> v1.2.1 Updating alloy-rpc-client v1.1.3 -> v1.2.1 Updating alloy-rpc-types v1.1.3 -> v1.2.1 Updating alloy-rpc-types-anvil v1.1.3 -> v1.2.1 Updating alloy-rpc-types-any v1.1.3 -> v1.2.1 Updating alloy-rpc-types-beacon v1.1.3 -> v1.2.1 Updating alloy-rpc-types-debug v1.1.3 -> v1.2.1 Updating alloy-rpc-types-engine v1.1.3 -> v1.2.1 Updating alloy-rpc-types-eth v1.1.3 -> v1.2.1 Updating alloy-rpc-types-trace v1.1.3 -> v1.2.1 Updating alloy-rpc-types-txpool v1.1.3 -> v1.2.1 Updating alloy-serde v1.1.3 -> v1.2.1 Updating alloy-signer v1.1.3 -> v1.2.1 Updating alloy-signer-aws v1.1.3 -> v1.2.1 Updating alloy-signer-gcp v1.1.3 -> v1.2.1 Updating alloy-signer-ledger v1.1.3 -> v1.2.1 Updating alloy-signer-local v1.1.3 -> v1.2.1 Updating alloy-signer-trezor v1.1.3 -> v1.2.1 Updating alloy-signer-turnkey v1.1.3 -> v1.2.1 Updating alloy-sol-macro v1.5.1 -> v1.5.2 Updating alloy-sol-macro-expander v1.5.1 -> v1.5.2 Updating alloy-sol-macro-input v1.5.1 -> v1.5.2 Updating alloy-sol-type-parser v1.5.1 -> v1.5.2 Updating alloy-sol-types v1.5.1 -> v1.5.2 Updating alloy-transport v1.1.3 -> v1.2.1 Updating alloy-transport-http v1.1.3 -> v1.2.1 Updating alloy-transport-ipc v1.1.3 -> v1.2.1 Updating alloy-transport-ws v1.1.3 -> v1.2.1 Updating alloy-trie v0.9.1 -> v0.9.2 Updating alloy-tx-macros v1.1.3 -> v1.2.1 Unchanged annotate-snippets v0.12.5 (available: v0.12.10) Unchanged anstyle-svg v0.1.11 (available: v0.1.12) Downgrading aws-smithy-runtime v1.9.6 -> v1.9.5 Updating axum-core v0.5.5 -> v0.5.6 Updating cc v1.2.50 -> v1.2.51 Updating derive_more v2.1.0 -> v2.1.1 Updating derive_more-impl v2.1.0 -> v2.1.1 Updating dtoa v1.0.10 -> v1.0.11 Updating find-msvc-tools v0.1.5 -> v0.1.6 Unchanged generic-array v0.14.7 (available: v0.14.9) Unchanged icu_collections v2.0.0 (available: v2.1.1) Unchanged icu_normalizer v2.0.1 (available: v2.1.1) Unchanged icu_normalizer_data v2.0.0 (available: v2.1.1) Unchanged icu_properties v2.0.2 (available: v2.1.2) Unchanged icu_properties_data v2.0.1 (available: v2.1.2) Unchanged idna_adapter v1.1.0 (available: v1.2.1) Updating itoa v1.0.15 -> v1.0.17 Updating jiff v0.2.16 -> v0.2.17 Updating jiff-static v0.2.16 -> v0.2.17 Updating libredox v0.1.11 -> v0.1.12 Updating libz-rs-sys v0.5.4 -> v0.5.5 Unchanged matchit v0.8.4 (available: v0.8.6) Unchanged mdbook v0.4.52 (available: v0.5.2) Updating portable-atomic v1.12.0 -> v1.13.0 Updating proc-macro2 v1.0.103 -> v1.0.104 Unchanged protobuf v3.3.0 (available: v3.7.2) Unchanged protobuf-support v3.3.0 (available: v3.7.2) Unchanged rand v0.8.5 (available: v0.9.2) Unchanged ratatui v0.29.0 (available: v0.30.0) Updating reqwest v0.12.26 -> v0.12.28 Updating ruint v1.17.0 -> v1.17.1 Updating rustix v1.1.2 -> v1.1.3 Updating ryu v1.0.21 -> v1.0.22 Updating schemars v1.1.0 -> v1.2.0 Updating schemars_derive v1.1.0 -> v1.2.0 Updating serde_json v1.0.145 -> v1.0.148 Updating signal-hook-registry v1.4.7 -> v1.4.8 Updating syn-solidity v1.5.1 -> v1.5.2 Updating tempfile v3.23.0 -> v3.24.0 Unchanged trezor-client v0.1.4 (available: v0.1.5) Unchanged unicode-width v0.2.0 (available: v0.2.2) Unchanged vergen v8.3.2 (available: v9.0.6) Updating zlib-rs v0.5.4 -> v0.5.5 Adding zmij v1.0.0 note: to see how you depend on a package, run `cargo tree --invert @` * touchups * touchups --------- Co-authored-by: mattsse <19890894+mattsse@users.noreply.github.com> Co-authored-by: Matthias Seitz * Update flake.lock (#12939) flake.lock: Update Flake lock file updates: • Updated input 'fenix': 'github:nix-community/fenix/16642c5' (2025-12-20) → 'github:nix-community/fenix/3479aaf' (2025-12-27) • Updated input 'fenix/rust-analyzer-src': 'github:rust-lang/rust-analyzer/ea1d299' (2025-12-18) → 'github:rust-lang/rust-analyzer/8c5a68e' (2025-12-26) • Updated input 'nixpkgs': 'github:NixOS/nixpkgs/7d853e5' (2025-12-19) → 'github:NixOS/nixpkgs/3edc4a3' (2025-12-27) Co-authored-by: github-actions[bot] Co-authored-by: DaniPopes <57450786+DaniPopes@users.noreply.github.com> * fix(chisel): uninitalized variables (#12937) * chore(deps): bump Swatinem/rust-cache from 2.8.1 to 2.8.2 (#12919) Bumps [Swatinem/rust-cache](https://github.com/swatinem/rust-cache) from 2.8.1 to 2.8.2. - [Release notes](https://github.com/swatinem/rust-cache/releases) - [Changelog](https://github.com/Swatinem/rust-cache/blob/master/CHANGELOG.md) - [Commits](https://github.com/swatinem/rust-cache/compare/f13886b937689c021905a6b90929199931d60db1...779680da715d629ac1d338a641029a2f4372abb5) --- updated-dependencies: - dependency-name: Swatinem/rust-cache dependency-version: 2.8.2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: zerosnacks <95942363+zerosnacks@users.noreply.github.com> * chore(deps): bump peter-evans/create-pull-request from 7.0.11 to 8.0.0 (#12918) Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 7.0.11 to 8.0.0. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/22a9089034f40e5a961c8808d113e2c98fb63676...98357b18bf14b5342f975ff684046ec3b2a07725) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-version: 8.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: grandizzy <38490174+grandizzy@users.noreply.github.com> * chore: sepolia rpc url (#12945) chore: sepolia rpc url private * chore(deps): bump crate-ci/typos from 1.40.0 to 1.40.1 (#12949) Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.40.0 to 1.40.1. - [Release notes](https://github.com/crate-ci/typos/releases) - [Changelog](https://github.com/crate-ci/typos/blob/master/CHANGELOG.md) - [Commits](https://github.com/crate-ci/typos/compare/2d0ce569feab1f8752f1dde43cc2f2aa53236e06...1a319b54cc9e3b333fed6a5c88ba1a90324da514) --- updated-dependencies: - dependency-name: crate-ci/typos dependency-version: 1.40.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump DeterminateSystems/determinate-nix-action from 3.15.0 to 3.15.1 (#12950) chore(deps): bump DeterminateSystems/determinate-nix-action Bumps [DeterminateSystems/determinate-nix-action](https://github.com/determinatesystems/determinate-nix-action) from 3.15.0 to 3.15.1. - [Release notes](https://github.com/determinatesystems/determinate-nix-action/releases) - [Commits](https://github.com/determinatesystems/determinate-nix-action/compare/95732e95d70db3ba1e0adc26a63c5e0375aba78c...1d699fc25db3f9e079cd2f168ca007a4183389be) --- updated-dependencies: - dependency-name: DeterminateSystems/determinate-nix-action dependency-version: 3.15.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump taiki-e/install-action from 2.65.1 to 2.65.7 (#12951) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.65.1 to 2.65.7. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/b9c5db3aef04caffaf95a1d03931de10fb2a140f...4c6723ec9c638cccae824b8957c5085b695c8085) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-version: 2.65.7 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * fix(config): err on unknown profile (#12946) * test: remove duplicate Issue2851 test (#12953) * chore(cheats): make sign(Wallet) pure (#12912) * chore(cheats): make sign(Wallet) pure * ignore --------- Co-authored-by: Matthias Seitz Co-authored-by: grandizzy <38490174+grandizzy@users.noreply.github.com> * fix(evm): use timestamp-based blob base fee calculation (#12959) * fix(evm): use timestamp-based blob base fee calculation * chore: use patch * Now BPO1 is default * bump to hardforks to 0.4.7 --------- Co-authored-by: Matthias Seitz * fix(config): reject bare versions in compilation restrictions (#12955) fmt Co-authored-by: tefyosL-sol * Revert "fix(config): err on unknown profile (#12946)" (#12964) This reverts commit 6ff4b52e2e572e93d0cd81591b1bd0e6ad9ed507. * fix(anvil): use B256 instead of TxHash for block hash parameters (#12961) Update mod.rs * Update crates/config/src/compilation.rs Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --------- Signed-off-by: dependabot[bot] Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: Matthias Seitz Co-authored-by: Claude Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: mattsse <19890894+mattsse@users.noreply.github.com> Co-authored-by: github-actions[bot] Co-authored-by: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: zerosnacks <95942363+zerosnacks@users.noreply.github.com> Co-authored-by: grandizzy <38490174+grandizzy@users.noreply.github.com> Co-authored-by: cakevm Co-authored-by: Theodore Solis Co-authored-by: tefyosL-sol Co-authored-by: Desant pivo Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> * Create ci-web3-gamefi.yml (#217) (#289) Introduce a basic CircleCI pipeline for the web3 GameFi project, providing a custom Docker executor and a stub job within a workflow. CI: Add CircleCI config file ci-web3-gamefi.yml with version 2.1 pipeline Define a custom executor using the cimg/base:stable Docker image with Docker Hub credentials Create a web3-defi-game-project- job and integrate it into a my-custom-workflow Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Merge pull request #47 (#290) * Add .circleci/config.yml * Updated config.yml * Updated config.yml * Updated config.yml * Update test.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 19: Workflow does not contain permissions Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Update test.yml (#46) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * chore(deps): bump revm to 24.0.0 (#10601) * feat: implement add_balance endpoint (#10636) * fix(bindings): ensure forge bind generates snake_case file names (#10622) * fix(bindings): ensure forge bind generates snake_case file names * refactor: use heck crate for snake_case conversion --------- Co-authored-by: zerosnacks <95942363+zerosnacks@users.noreply.github.com> * chore: standardize lint help + validate docs existance (#10639) * feat(cast mktx): add support for "--ethsign" option (#10641) - Sign transactions using "eth_signTransaction" on local node with unlocked accounts. - Same TX building logic as in "cast send --unlocked". - Added a test case to validate the new functionality. * chore(wallets): improve error message for signer instantiation failure (#10646) chore(wallets): improve error message on signer instantiation failure * chore: replaced anvil hardforks with alloy hardforks (#10612) * chore: replaced anvil hardforks with alloy hardforks * fixes * fixes * fixes * removed redundant op and alloy hardforks enum * fixes * fixes * bumped alloy hardforks and kept default to prague and isthmus * bumped alloy-hardforks and fixes --------- Co-authored-by: zerosnacks <95942363+zerosnacks@users.noreply.github.com> * fix(`anvil`): latest evm version should be prague (#10653) * fix(`anvil`): latest evm version should be prague * fix test * nit * chore(deps): bump tracing-subscriber (#51) Bumps the cargo group with 1 update in the / directory: [tracing-subscriber](https://github.com/tokio-rs/tracing). Updates `tracing-subscriber` from 0.3.19 to 0.3.20 - [Release notes](https://github.com/tokio-rs/tracing/releases) - [Commits](https://github.com/tokio-rs/tracing/compare/tracing-subscriber-0.3.19...tracing-subscriber-0.3.20) --- updated-dependencies: - dependency-name: tracing-subscriber dependency-version: 0.3.20 dependency-type: direct:production dependency-group: cargo ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Update test.yml (#52) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Update docker-image.yml (#53) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Create ci_cargo.yml (#59) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Create web3_defi_gamefi.yml (#61) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Update dependencies.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 21: Workflow does not contain permissions Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Update dependencies.yml Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update dependencies.yml (#247) Improve readability of the GitHub Actions dependencies workflow by adjusting whitespace and adding blank lines CI: Add blank line before the workflow name declaration Insert blank line after the scheduled cron job entry Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update dependencies.yml (#248) CI: Remove extraneous blank line in .github/workflows/dependencies.yml Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update test.yml (#249) CI: Remove dev branch from test workflow triggers Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --------- Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Signed-off-by: dependabot[bot] Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Co-authored-by: zerosnacks <95942363+zerosnacks@users.noreply.github.com> Co-authored-by: pistomat Co-authored-by: zark <77061323+zarkk01@users.noreply.github.com> Co-authored-by: 0xrusowsky <90208954+0xrusowsky@users.noreply.github.com> Co-authored-by: Mablr <59505383+mablr@users.noreply.github.com> Co-authored-by: Ishika Choudhury <117741714+Rimeeeeee@users.noreply.github.com> Co-authored-by: Yash Atreya <44857776+yash-atreya@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Update crates/evm/evm/src/executors/corpus.rs Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Foundry/master test ux (#295) * Update ci.yml Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update ci.yml (#211) This pull request updates the Rust version in the CircleCI workflow to 1.89.0. This is a good maintenance task to keep the CI environment up-to-date. I have one suggestion regarding the Docker image tag to potentially simplify future maintenance by automatically adopting patch releases. Overall, the change is correct and beneficial. Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update test.yml (#250) CI: Include the 'main' branch in the push event triggers for the test workflow Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --------- Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * fix(fmt): handle trailing coments between base contracts (#296) (#299) @0xrusowsky @Dargon789 fix(fmt): handle trailing coments between base contracts Revert 142 master (#296) * Create ci_cargo.yml (#72) * Create config.yml * Rename ci_cargo.yml to cargo.yml * fix(fmt): handle trailing coments between base contracts (#12127) * fix(fmt): account for ternary operators when estimating size * fix(fmt): handle comments between inherited base contracts * test: layout + base inheritance * Revert "fix(fmt): handle trailing coments between base contracts (#12127)" This reverts commit b8b5fbb83fa2436063cebc34ddf900abc972b11d. * Update cargo.yml (#172) CI/CD Configuration Update: The CircleCI configuration file, .circleci/cargo.yml, has been updated to use a newer version of the Rust Docker image. Rust Toolchain Version Bump: The cimg/rust Docker image version has been incremented from 1.88.0 to 1.89.0, ensuring builds and tests run with the latest stable Rust toolchain. * Fix cloning of compiler settings for Vyper input Replace context.clone().compiler_settings.vyper with context.compiler_settings.vyper.clone() to avoid unnecessary cloning of the entire VerificationContext. This reduces memory allocations when creating VyperInput instances. Applied to both etherscan and sourcify verification providers. * Remove duplicate logic in TxSigner::address() implementations --------- Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: 0xrusowsky <90208954+0xrusowsky@users.noreply.github.com> Co-authored-by: Gengar Co-authored-by: Aganis * Update CircleCI configuration for dev stage (#300) fix Automatic reruns provide a safety net for your CI/CD pipelines by automatically retrying failed steps and/or workflows. Automatic reruns help teams maintain productivity by reducing the need for manual intervention when steps and workflows fail due to temporary issues. Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * EIP-4788 implementation * formatting * add beacon block root tests * Update crates/evm/evm/src/executors/trace.rs Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update crates/cast/src/cmd/run.rs Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * feat: upgrade @types/node from 24.10.4 to 25.0.2 Snyk has created this PR to upgrade @types/node from 24.10.4 to 25.0.2. See this package in npm: @types/node See this project in Snyk: https://app.snyk.io/org/dargon789/project/8da85645-409e-46fa-bd46-9b58e7905fb8?utm_source=github-cloud-app&utm_medium=referral&page=upgrade-pr * fix: `svm fails to download solc 0.8.33 on linux/arm64`, bump `svm-rs` (#13007) (#309) bump svm-rs Co-authored-by: zerosnacks <95942363+zerosnacks@users.noreply.github.com> * Ethereumjs/master (#310) * Potential fix for code scanning alert no. 19: Workflow does not contain permissions Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 61: Workflow does not contain permissions Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 74: Artifact poisoning Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Create config.yml (#105) * Create cargo.yml (#106) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Delete .github/workflows/docker-image.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Rename ci_cargo.yml to cargo.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * fix(fmt): handle trailing coments between base contracts (#12127) * fix(fmt): account for ternary operators when estimating size * fix(fmt): handle comments between inherited base contracts * test: layout + base inheritance * Revert "fix(fmt): handle trailing coments between base contracts (#12127)" This reverts commit b8b5fbb83fa2436063cebc34ddf900abc972b11d. * Update cargo.yml (#172) CI/CD Configuration Update: The CircleCI configuration file, .circleci/cargo.yml, has been updated to use a newer version of the Rust Docker image. Rust Toolchain Version Bump: The cimg/rust Docker image version has been incremented from 1.88.0 to 1.89.0, ensuring builds and tests run with the latest stable Rust toolchain. Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Revert "Create cargo.yml (#106)" This reverts commit 251a2b4fce0c50e3426ffb2022d9abef5b948fa9. * Create cargo.yml (#213) https://github.com/apps/gemini-code-assist Code Review This pull request introduces a CircleCI workflow to automate formatting checks and tests. My review has identified two main issues in the configuration: redundant steps that would unnecessarily increase job execution time, and a mismatch between the Rust version in the CI environment and the one specified in the project's Cargo.toml. I've provided suggestions to fix these issues for a more efficient and consistent CI process. Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Create docker.yml Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Remove duplicate logic in TxSigner::address() implementations * fix(fmt): handle trailing coments between base contracts (#296) @0xrusowsky @Dargon789 fix(fmt): handle trailing coments between base contracts Revert 142 master (#296) * Create ci_cargo.yml (#72) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Create config.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Rename ci_cargo.yml to cargo.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * fix(fmt): handle trailing coments between base contracts (#12127) * fix(fmt): account for ternary operators when estimating size * fix(fmt): handle comments between inherited base contracts * test: layout + base inheritance * Revert "fix(fmt): handle trailing coments between base contracts (#12127)" This reverts commit b8b5fbb83fa2436063cebc34ddf900abc972b11d. * Update cargo.yml (#172) CI/CD Configuration Update: The CircleCI configuration file, .circleci/cargo.yml, has been updated to use a newer version of the Rust Docker image. Rust Toolchain Version Bump: The cimg/rust Docker image version has been incremented from 1.88.0 to 1.89.0, ensuring builds and tests run with the latest stable Rust toolchain. Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Fix cloning of compiler settings for Vyper input Replace context.clone().compiler_settings.vyper with context.compiler_settings.vyper.clone() to avoid unnecessary cloning of the entire VerificationContext. This reduces memory allocations when creating VyperInput instances. Applied to both etherscan and sourcify verification providers. * Remove duplicate logic in TxSigner::address() implementations --------- Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: 0xrusowsky <90208954+0xrusowsky@users.noreply.github.com> Co-authored-by: Gengar Co-authored-by: Aganis --------- Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Co-authored-by: 0xrusowsky <90208954+0xrusowsky@users.noreply.github.com> Co-authored-by: Aganis Co-authored-by: Gengar * Forge/master (#311) * Potential fix for code scanning alert no. 19: Workflow does not contain permissions Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 61: Workflow does not contain permissions Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 74: Artifact poisoning Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Create config.yml (#105) * Create cargo.yml (#106) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Delete .github/workflows/docker-image.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Rename ci_cargo.yml to cargo.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * fix(fmt): handle trailing coments between base contracts (#12127) * fix(fmt): account for ternary operators when estimating size * fix(fmt): handle comments between inherited base contracts * test: layout + base inheritance * Revert "fix(fmt): handle trailing coments between base contracts (#12127)" This reverts commit b8b5fbb83fa2436063cebc34ddf900abc972b11d. * Update cargo.yml (#172) CI/CD Configuration Update: The CircleCI configuration file, .circleci/cargo.yml, has been updated to use a newer version of the Rust Docker image. Rust Toolchain Version Bump: The cimg/rust Docker image version has been incremented from 1.88.0 to 1.89.0, ensuring builds and tests run with the latest stable Rust toolchain. Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Revert "Create cargo.yml (#106)" This reverts commit 251a2b4fce0c50e3426ffb2022d9abef5b948fa9. * Create cargo.yml (#213) https://github.com/apps/gemini-code-assist Code Review This pull request introduces a CircleCI workflow to automate formatting checks and tests. My review has identified two main issues in the configuration: redundant steps that would unnecessarily increase job execution time, and a mismatch between the Rust version in the CI environment and the one specified in the project's Cargo.toml. I've provided suggestions to fix these issues for a more efficient and consistent CI process. Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Create ci-web3-gamefi.yml (#217) Introduce a basic CircleCI pipeline for the web3 GameFi project, providing a custom Docker executor and a stub job within a workflow. CI: Add CircleCI config file ci-web3-gamefi.yml with version 2.1 pipeline Define a custom executor using the cimg/base:stable Docker image with Docker Hub credentials Create a web3-defi-game-project- job and integrate it into a my-custom-workflow Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Remove duplicate logic in TxSigner::address() implementations * fix(fmt): handle trailing coments between base contracts (#296) @0xrusowsky @Dargon789 fix(fmt): handle trailing coments between base contracts Revert 142 master (#296) * Create ci_cargo.yml (#72) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Create config.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Rename ci_cargo.yml to cargo.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * fix(fmt): handle trailing coments between base contracts (#12127) * fix(fmt): account for ternary operators when estimating size * fix(fmt): handle comments between inherited base contracts * test: layout + base inheritance * Revert "fix(fmt): handle trailing coments between base contracts (#12127)" This reverts commit b8b5fbb83fa2436063cebc34ddf900abc972b11d. * Update cargo.yml (#172) CI/CD Configuration Update: The CircleCI configuration file, .circleci/cargo.yml, has been updated to use a newer version of the Rust Docker image. Rust Toolchain Version Bump: The cimg/rust Docker image version has been incremented from 1.88.0 to 1.89.0, ensuring builds and tests run with the latest stable Rust toolchain. Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Fix cloning of compiler settings for Vyper input Replace context.clone().compiler_settings.vyper with context.compiler_settings.vyper.clone() to avoid unnecessary cloning of the entire VerificationContext. This reduces memory allocations when creating VyperInput instances. Applied to both etherscan and sourcify verification providers. * Remove duplicate logic in TxSigner::address() implementations --------- Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: 0xrusowsky <90208954+0xrusowsky@users.noreply.github.com> Co-authored-by: Gengar Co-authored-by: Aganis --------- Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Co-authored-by: 0xrusowsky <90208954+0xrusowsky@users.noreply.github.com> Co-authored-by: Aganis Co-authored-by: Gengar * Update dev_stage.yml (#313) (#315) * Update dev_stage.yml (#313) Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update .circleci/dev_stage.yml Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --------- Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> * Foundry/main (#316) * chore(deps): bump the cargo group across 1 directory with 2 updates Bumps the cargo group with 2 updates in the / directory: [tracing-subscriber](https://github.com/tokio-rs/tracing) and [ammonia](https://github.com/rust-ammonia/ammonia). Updates `tracing-subscriber` from 0.3.19 to 0.3.20 - [Release notes](https://github.com/tokio-rs/tracing/releases) - [Commits](https://github.com/tokio-rs/tracing/compare/tracing-subscriber-0.3.19...tracing-subscriber-0.3.20) Updates `ammonia` from 4.1.0 to 4.1.2 - [Release notes](https://github.com/rust-ammonia/ammonia/releases) - [Changelog](https://github.com/rust-ammonia/ammonia/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-ammonia/ammonia/compare/v4.1.0...v4.1.2) --- updated-dependencies: - dependency-name: tracing-subscriber dependency-version: 0.3.20 dependency-type: direct:production dependency-group: cargo - dependency-name: ammonia dependency-version: 4.1.2 dependency-type: indirect dependency-group: cargo ... Signed-off-by: dependabot[bot] * Update crates/verify/src/provider.rs Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update crates/doc/src/writer/as_doc.rs Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update as_doc.rs (#235) Tidy up formatting in as_doc.rs by removing extraneous blank lines in the Document::as_doc implementation Enhancements: Remove unnecessary blank line before initializing bases Remove unnecessary blank line before writing state variables Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --------- Signed-off-by: dependabot[bot] Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * chore: ignore RUSTSEC (#13011) * update deny for CI * Update more * chore(chisel): rm dead code (#13014) * chore(cli): rm dead code (#13015) * chore(cheatcodes): rm dead code (#13016) * chore(common): rm dead code (#13018) * chore(bench): rm dead code (#13017) * fix(forge): respect lint ignore config in solar compilation (#12978) Co-authored-by: tefyosL-sol * fix: deduplicate submodule status check logic (#13010) Update mod.rs * Foundry/ethereum ux fix tempo #296 (#319) * Potential fix for code scanning alert no. 19: Workflow does not contain permissions Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 61: Workflow does not contain permissions Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 74: Artifact poisoning Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Create config.yml (#105) * Create cargo.yml (#106) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Delete .github/workflows/docker-image.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Rename ci_cargo.yml to cargo.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * fix(fmt): handle trailing coments between base contracts (#12127) * fix(fmt): account for ternary operators when estimating size * fix(fmt): handle comments between inherited base contracts * test: layout + base inheritance * Revert "fix(fmt): handle trailing coments between base contracts (#12127)" This reverts commit b8b5fbb83fa2436063cebc34ddf900abc972b11d. * Update cargo.yml (#172) CI/CD Configuration Update: The CircleCI configuration file, .circleci/cargo.yml, has been updated to use a newer version of the Rust Docker image. Rust Toolchain Version Bump: The cimg/rust Docker image version has been incremented from 1.88.0 to 1.89.0, ensuring builds and tests run with the latest stable Rust toolchain. Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Revert "Create cargo.yml (#106)" This reverts commit 251a2b4fce0c50e3426ffb2022d9abef5b948fa9. * Create cargo.yml (#213) https://github.com/apps/gemini-code-assist Code Review This pull request introduces a CircleCI workflow to automate formatting checks and tests. My review has identified two main issues in the configuration: redundant steps that would unnecessarily increase job execution time, and a mismatch between the Rust version in the CI environment and the one specified in the project's Cargo.toml. I've provided suggestions to fix these issues for a more efficient and consistent CI process. Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Remove duplicate logic in TxSigner::address() implementations * fix(fmt): handle trailing coments between base contracts (#296) @0xrusowsky @Dargon789 fix(fmt): handle trailing coments between base contracts Revert 142 master (#296) * Create ci_cargo.yml (#72) Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Create config.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Rename ci_cargo.yml to cargo.yml Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * fix(fmt): handle trailing coments between base contracts (#12127) * fix(fmt): account for ternary operators when estimating size * fix(fmt): handle comments between inherited base contracts * test: layout + base inheritance * Revert "fix(fmt): handle trailing coments between base contracts (#12127)" This reverts commit b8b5fbb83fa2436063cebc34ddf900abc972b11d. * Update cargo.yml (#172) CI/CD Configuration Update: The CircleCI configuration file, .circleci/cargo.yml, has been updated to use a newer version of the Rust Docker image. Rust Toolchain Version Bump: The cimg/rust Docker image version has been incremented from 1.88.0 to 1.89.0, ensuring builds and tests run with the latest stable Rust toolchain. Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> * Fix cloning of compiler settings for Vyper input Replace context.clone().compiler_settings.vyper with context.compiler_settings.vyper.clone() to avoid unnecessary cloning of the entire VerificationContext. This reduces memory allocations when creating VyperInput instances. Applied to both etherscan and sourcify verification providers. * Remove duplicate logic in TxSigner::address() implementations --------- Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: 0xrusowsky <90208954+0xrusowsky@users.noreply.github.com> Co-authored-by: Gengar Co-authored-by: Aganis --------- Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Co-authored-by: 0xrusowsky <90208954+0xrusowsky@users.noreply.github.com> Co-authored-by: Aganis Co-authored-by: Gengar * Potential fix for code scanning alert no. 94: Uncontrolled data used in path expression Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 104: Uncontrolled data used in path expression Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Potential fix for code scanning alert no. 105: Server-side request forgery Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * fix: add Tempo transaction receipt type support in TryFrom conversion (#334) * fix: add Tempo transaction receipt type support in TryFrom conversion (#13047) Amp-Thread-ID: https://ampcode.com/threads/T-019bbf45-d7c8-75ed-8c05-bc1638d487ee Co-authored-by: Matthias Seitz Co-authored-by: Amp * feat(cheatcodes): add getRecordedLogsJson cheatcode (#13093) Adds a new cheatcode `getRecordedLogsJson` that returns recorded logs as a JSON string, similar to the existing `getStateDiffJson` pattern. This allows users to easily post-process recorded logs externally without needing to manually transform the Log[] array to JSON. JSON format: ```json [{"topics": ["0x..."], "data": "0x...", "emitter": "0x..."}] ``` Closes #12854 * feat: add Sourcify support to forge clone (#12900) * Integrate Sourcify API for contract cloning Added support for Sourcify API in `forge clone` command. * Add reqwest dependency with json feature * Remove unused import in clone.rs Removed unused import of BTreeMap. * Refactor EtherscanClient to ExplorerClient * Change sourcify module from private to public * Implement test for sourcify clone functionality Add test for cloning with sourcify source * Update clone.rs * Add url dependency to Cargo.toml * cargo fmt * Enhance Sourcify client with cached creation data Updated the Sourcify client to cache creation data and reuse it across API calls, improving efficiency. Modified the contract source code retrieval to include additional creation data fields. * Improve error handling for contract data retrieval Refactor contract source code and creation data retrieval to use fallback values when API requests fail or fields are unavailable. * Enhance contract_source_code with improved caching Updated contract_source_code to include additional fields in the API request and improved caching of creation data. Removed fallback logic for fetching creation data from the API. * Refactor creation_data handling in clone.rs Removed redundant creation_data initialization and caching. * Refactor response deserialization to use untagged enum * fix: use serde_json::Value for abi in Sourcify parsing The #[serde(untagged)] enum SourcifyContractResponse failed to deserialize because Box doesn't work with untagged enums. RawValue requires borrowing from the original JSON, but untagged enums buffer data during variant matching. Changes: - Change abi field from Box to serde_json::Value - Truncate response in error messages to avoid huge output * feat: add --sourcify-url option for custom Sourcify API endpoint * feat: imply --source sourcify when --sourcify-url is specified * feat: support full path in --sourcify-url When --sourcify-url contains v2/contract/chain, only append address and fields instead of building the full path again. --------- Co-authored-by: grandizzy * perf: add dist profile for smaller release binaries (#13097) * perf: add dist profile for smaller release binaries Add a new 'dist' Cargo profile optimized for distribution: - Fat LTO and codegen-units=1 for better optimization - Strip symbols for smaller binaries - opt-level="s" overrides for non-perf-critical dependencies Benchmarks on Solady test suite show dist is 8% faster than release while being 45% smaller (43MB vs 78MB). Update release workflows to use the dist profile instead of maxperf. * Apply suggestion from @DaniPopes --------- Co-authored-by: DaniPopes <57450786+DaniPopes@users.noreply.github.com> * chore(deps): update figment to figment2 v0.11 (#13099) * chore(deps): update figment to figment2 v0.11 * rename * feat: add precompile decoding for Prague BLS12-381 and Osaka P256VERIFY (#13094) * feat: add precompile decoding for Prague BLS12-381 and Osaka P256VERIFY * wip * wip * fix(traces): use raw byte decoding for P256VERIFY precompile P256VERIFY (RIP-7212) uses concatenated raw bytes, not ABI encoding: - Input: hash (32) + r (32) + s (32) + qx (32) + qy (32) = 160 bytes - Output: 32 bytes where 0x...01 means success * fix(traces): use raw byte decoding for all precompiles Precompiles use concatenated raw bytes, not ABI encoding: - ecrecover: hash (32) + v (32) + r (32) + s (32), returns address in last 20 bytes - sha256/ripemd160: raw input, raw 32-byte output (ripemd in last 20 bytes) - ecadd: x1/y1/x2/y2 (32 each), returns x/y (32 each) - ecmul: x1/y1/s (32 each), returns x/y (32 each) - ecpairing: returns 32-byte bool (1 = success) - bls12PairingCheck: returns 32-byte bool (1 = success) * fix(traces): restore ABI-based precompile decoding * fix * fix(anvil): use suggested priority fee by default (#13092) * fix(anvil): use suggested priority fee by default * test: fix anvil trace expectations --------- Co-authored-by: tefyosL-sol * chore: aggregate PRs (#13100) * chore: aggregate PRs This PR aggregates changes from the following PRs: - Closes #13032 by @\splinter012 - Closes #13059 by @\phrwlk * fmt * chore(evm): misleading error message in traces serialization (#13081) Co-authored-by: tefyosL-sol --------- Co-authored-by: Desant pivo Co-authored-by: Matthias Seitz Co-authored-by: Amp Co-authored-by: grandizzy <38490174+grandizzy@users.noreply.github.com> Co-authored-by: Avory Co-authored-by: grandizzy Co-authored-by: onbjerg Co-authored-by: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Co-authored-by: Theodore Solis Co-authored-by: tefyosL-sol * Potential fix for code scanning alert no. 103: Artifact poisoning (#336) Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> * Update docker.yml --------- Signed-off-by: dependabot[bot] Signed-off-by: AU_gdev_19 <64915515+Dargon789@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: zerosnacks <95942363+zerosnacks@users.noreply.github.com> Co-authored-by: pistomat Co-authored-by: zark <77061323+zarkk01@users.noreply.github.com> Co-authored-by: 0xrusowsky <90208954+0xrusowsky@users.noreply.github.com> Co-authored-by: Mablr <59505383+mablr@users.noreply.github.com> Co-authored-by: Ishika Choudhury <117741714+Rimeeeeee@users.noreply.github.com> Co-authored-by: Yash Atreya <44857776+yash-atreya@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> Co-authored-by: grandizzy <38490174+grandizzy@users.noreply.github.com> Co-authored-by: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Co-authored-by: grandizzy Co-authored-by: Rafael Quintero <32346241+rplusq@users.noreply.github.com> Co-authored-by: rplusq Co-authored-by: Claude Co-authored-by: snyk-io[bot] <141718529+snyk-io[bot]@users.noreply.github.com> Co-authored-by: Gengar Co-authored-by: Haythem Sellami <17862704+haythemsellami@users.noreply.github.com> Co-authored-by: cakevm Co-authored-by: Matthias Seitz Co-authored-by: Theodore Solis Co-authored-by: tefyosL-sol Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: mattsse <19890894+mattsse@users.noreply.github.com> Co-authored-by: github-actions[bot] Co-authored-by: Desant pivo Co-authored-by: Aganis Co-authored-by: tskoyo Co-authored-by: Matt D Co-authored-by: onbjerg Co-authored-by: Maxim Evtush <154841002+maximevtush@users.noreply.github.com> Co-authored-by: Amp Co-authored-by: Avory --- .circleci/cargo.yml | 32 +++ .circleci/ci-web3-gamefi.yml | 26 +++ .circleci/ci.yml | 31 +++ .circleci/ci_cargo.yml | 37 +++ .circleci/ci_v1.yml | 31 +++ .circleci/config.yml | 32 +++ .circleci/dev_stage.yml | 70 ++++++ .circleci/web3_defi_gamefi.yml | 26 +++ .codesandbox/tasks.json | 7 + .deps/remix-tests/remix_accounts.sol | 39 ++++ .deps/remix-tests/remix_tests.sol | 225 +++++++++++++++++++ .github/ISSUE_TEMPLATE/bug_report.md | 39 ++++ .github/ISSUE_TEMPLATE/custom.md | 10 + .github/ISSUE_TEMPLATE/feature_request.md | 20 ++ .github/workflows/apisec-scan.yml | 29 +++ .github/workflows/codeql.yml | 92 ++++++++ .github/workflows/deploy.yml | 27 +++ .github/workflows/docker.yml | 62 +++++ .github/workflows/google.yml | 117 ++++++++++ .github/workflows/npm.yml | 37 +++ .github/workflows/snyk-container.yml | 55 +++++ .gitmodules | 6 + benches/src/lib.rs | 16 +- counter/.github/workflows/test.yml | 43 ++++ counter/.gitignore | 14 ++ counter/README.md | 66 ++++++ counter/foundry.toml | 6 + counter/lib/forge-std | 1 + counter/lib/openzeppelin-contracts | 1 + counter/script/Counter.s.sol | 19 ++ counter/src/Counter.sol | 14 ++ counter/test/Counter.t.sol | 24 ++ crates/cast/src/cmd/run.rs | 14 +- crates/cast/tests/cli/main.rs | 28 +++ crates/cli/src/utils/suggestions.rs | 3 +- crates/common/src/contracts.rs | 2 +- crates/doc/src/parser/comment.rs | 6 + crates/doc/src/writer/as_doc.rs | 35 ++- crates/doc/src/writer/buf_writer.rs | 20 +- crates/evm/evm/src/executors/trace.rs | 28 ++- crates/forge/Cargo.toml | 1 + crates/forge/tests/cli/test_optimizer.rs | 1 - crates/lint/src/linter.rs | 129 +++++++++++ crates/lint/src/sol/gas/keccak.rs | 98 +------- crates/script-sequence/src/sequence.rs | 10 +- crates/script/src/simulate.rs | 10 +- crates/test-utils/src/script.rs | 29 ++- crates/verify/src/etherscan/standard_json.rs | 2 +- flake.nix | 10 +- npm/package.json | 2 +- npm/scripts/stage-from-artifact.mjs | 28 ++- npm/src/const.mjs | 30 ++- 52 files changed, 1588 insertions(+), 152 deletions(-) create mode 100644 .circleci/cargo.yml create mode 100644 .circleci/ci-web3-gamefi.yml create mode 100644 .circleci/ci.yml create mode 100644 .circleci/ci_cargo.yml create mode 100644 .circleci/ci_v1.yml create mode 100644 .circleci/config.yml create mode 100644 .circleci/dev_stage.yml create mode 100644 .circleci/web3_defi_gamefi.yml create mode 100644 .codesandbox/tasks.json create mode 100644 .deps/remix-tests/remix_accounts.sol create mode 100644 .deps/remix-tests/remix_tests.sol create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/custom.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md create mode 100644 .github/workflows/apisec-scan.yml create mode 100644 .github/workflows/codeql.yml create mode 100644 .github/workflows/deploy.yml create mode 100644 .github/workflows/docker.yml create mode 100644 .github/workflows/google.yml create mode 100644 .github/workflows/snyk-container.yml create mode 100644 .gitmodules create mode 100644 counter/.github/workflows/test.yml create mode 100644 counter/.gitignore create mode 100644 counter/README.md create mode 100644 counter/foundry.toml create mode 160000 counter/lib/forge-std create mode 160000 counter/lib/openzeppelin-contracts create mode 100644 counter/script/Counter.s.sol create mode 100644 counter/src/Counter.sol create mode 100644 counter/test/Counter.t.sol create mode 100644 crates/lint/src/linter.rs diff --git a/.circleci/cargo.yml b/.circleci/cargo.yml new file mode 100644 index 0000000000000..32b65e6a23cc5 --- /dev/null +++ b/.circleci/cargo.yml @@ -0,0 +1,32 @@ +version: 2.1 +# +jobs: + build-and-test: + docker: + - image: cimg/rust:1.89.0 + steps: + - checkout + - restore_cache: + keys: + - v1-cargo-{{ checksum "Cargo.lock" }} + - v1-cargo- + - run: + name: "Check formatting" + command: cargo fmt -- --check + - run: + name: "Run tests" + command: cargo test + - save_cache: + key: v1-cargo-{{ checksum "Cargo.lock" }} + paths: + - "~/.cargo/bin" + - "~/.cargo/registry/index" + - "~/.cargo/registry/cache" + - "~/.cargo/git/db" + - "target" + - run: + name: "Check formatting" + command: cargo fmt -- --check + - run: + name: "Run tests" + command: cargo test diff --git a/.circleci/ci-web3-gamefi.yml b/.circleci/ci-web3-gamefi.yml new file mode 100644 index 0000000000000..ad53a8e498202 --- /dev/null +++ b/.circleci/ci-web3-gamefi.yml @@ -0,0 +1,26 @@ +# Use the latest 2.1 version of CircleCI pipeline process engine. +# See: https://circleci.com/docs/configuration-reference + +version: 2.1 +executors: + my-custom-executor: + docker: + - image: cimg/base:stable + auth: + # ensure you have first added these secrets + # visit app.circleci.com/settings/project/github/Dargon789/foundry/environment-variables + username: $DOCKER_HUB_USER + password: $DOCKER_HUB_PASSWORD +jobs: + web3-defi-game-project-: + + executor: my-custom-executor + steps: + - checkout + - run: | + # echo Hello, World! + +workflows: + my-custom-workflow: + jobs: + - web3-defi-game-project- diff --git a/.circleci/ci.yml b/.circleci/ci.yml new file mode 100644 index 0000000000000..1b5df6d6e668e --- /dev/null +++ b/.circleci/ci.yml @@ -0,0 +1,31 @@ +version: 2.1 +jobs: + build-and-test: + docker: + - image: cimg/rust:1.89.0 + steps: + - checkout + - restore_cache: + keys: + - v1-cargo-{{ checksum "Cargo.lock" }} + - v1-cargo- + - run: + name: "Check formatting" + command: cargo fmt -- --check + - run: + name: "Run tests" + command: cargo test + - save_cache: + key: v1-cargo-{{ checksum "Cargo.lock" }} + paths: + - "~/.cargo/bin" + - "~/.cargo/registry/index" + - "~/.cargo/registry/cache" + - "~/.cargo/git/db" + - "target" + - run: + name: "Check formatting" + command: cargo fmt -- --check + - run: + name: "Run tests" + command: cargo test diff --git a/.circleci/ci_cargo.yml b/.circleci/ci_cargo.yml new file mode 100644 index 0000000000000..46a18d45a5fca --- /dev/null +++ b/.circleci/ci_cargo.yml @@ -0,0 +1,37 @@ +version: 2.1 + +jobs: + build-and-test: + docker: + - image: cimg/rust:1.88.0 + steps: + - checkout + - restore_cache: + keys: + - v1-cargo-{{ checksum "Cargo.lock" }} + - v1-cargo- + - run: + name: "Check formatting" + command: cargo fmt -- --check + - run: + name: "Run tests" + command: cargo test + - save_cache: + key: v1-cargo-{{ checksum "Cargo.lock" }} + paths: + - "~/.cargo/bin" + - "~/.cargo/registry/index" + - "~/.cargo/registry/cache" + - "~/.cargo/git/db" + - "target" + - run: + name: "Check formatting" + command: cargo fmt -- --check + - run: + name: "Run tests" + command: cargo test + +workflows: + ci: + jobs: + - build-and-test diff --git a/.circleci/ci_v1.yml b/.circleci/ci_v1.yml new file mode 100644 index 0000000000000..82c6de5b42b73 --- /dev/null +++ b/.circleci/ci_v1.yml @@ -0,0 +1,31 @@ +version: 2.1 + +jobs: + build-and-test: + docker: + - image: cimg/rust:1.89.0 + steps: + - checkout + - restore_cache: + keys: + - v1-cargo-{{ checksum "Cargo.lock" }} + - v1-cargo- + - run: + name: "Check formatting" + command: cargo fmt -- --check + - run: + name: "Run tests" + command: cargo test + - save_cache: + key: v1-cargo-{{ checksum "Cargo.lock" }} + paths: + - "~/.cargo/bin" + - "~/.cargo/registry/index" + - "~/.cargo/registry/cache" + - "~/.cargo/git/db" + - "target" + +workflows: + ci: + jobs: + - build-and-test diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000000000..4168efef0971f --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,32 @@ +# Use the latest 2.1 version of CircleCI pipeline process engine. +# See: https://circleci.com/docs/reference/configuration-reference +version: 2.1 + +# Define a job to be invoked later in a workflow. +# See: https://circleci.com/docs/guides/orchestrate/jobs-steps/#jobs-overview & https://circleci.com/docs/reference/configuration-reference/#jobs +jobs: + say-hello: + # Specify the execution environment. You can specify an image from Docker Hub or use one of our convenience images from CircleCI's Developer Hub. + # See: https://circleci.com/docs/guides/execution-managed/executor-intro/ & https://circleci.com/docs/reference/configuration-reference/#executor-job + docker: + # Specify the version you desire here + # See: https://circleci.com/developer/images/image/cimg/base + - image: cimg/base:current + + # Add steps to the job + # See: https://circleci.com/docs/guides/orchestrate/jobs-steps/#steps-overview & https://circleci.com/docs/reference/configuration-reference/#steps + steps: + # Checkout the code as the first step. + - checkout + - run: + name: "Say hello" + command: "echo Hello, World!" + +# Orchestrate jobs using workflows +# See: https://circleci.com/docs/guides/orchestrate/workflows/ & https://circleci.com/docs/reference/configuration-reference/#workflows +workflows: + say-hello-workflow: # This is the name of the workflow, feel free to change it to better match your workflow. + # Inside the workflow, you define the jobs you want to run. + jobs: + - say-hello + diff --git a/.circleci/dev_stage.yml b/.circleci/dev_stage.yml new file mode 100644 index 0000000000000..5ba351727d22b --- /dev/null +++ b/.circleci/dev_stage.yml @@ -0,0 +1,70 @@ +# Use the latest 2.1 version of CircleCI pipeline process engine. +# See: https://circleci.com/docs/configuration-reference + +version: 2.1 +executors: + my-custom-executor: + docker: + - image: cimg/base:stable +jobs: + web3-defi-game-project-: + + executor: my-custom-executor + steps: + - checkout + - run: | + # echo Hello, World! + +workflows: + my-custom-workflow: + jobs: + - web3-defi-game-project- + + jobs: + my-job: + steps: + - run: echo "Hello, world!" + - run: + command: echo "This step will automatically rerun up to 3 times if it fails with a 10 second delay between attempts" + max_auto_reruns: 3 + auto_rerun_delay: 10s + + workflows: + dev_stage_pre-prod: + jobs: + - test_dev: + filters: # using regex filters requires the entire branch to match + branches: + only: # only branches matching the below regex filters will run + - dev + - /user-.*/ + - test_stage: + filters: + branches: + only: stage + - test_pre-prod: + filters: + branches: + only: /pre-prod(?:-.+)?$/ + + + build-test-deploy: + jobs: + - build: + filters: # required since `test` has tag filters AND requires `build` + tags: + only: /^config-test.*/ + - test: + requires: + - build + filters: # required since `deploy` has tag filters AND requires `test` + tags: + only: /^config-test.*/ + - deploy: + requires: + - test + filters: + tags: + only: /^config-test.*/ + branches: + ignore: /.*/ diff --git a/.circleci/web3_defi_gamefi.yml b/.circleci/web3_defi_gamefi.yml new file mode 100644 index 0000000000000..edb6605e3f101 --- /dev/null +++ b/.circleci/web3_defi_gamefi.yml @@ -0,0 +1,26 @@ +# Use the latest 2.1 version of CircleCI pipeline process engine. +# See: https://circleci.com/docs/configuration-reference + +version: 2.1 +executors: + my-custom-executor: + docker: + - image: cimg/base:stable + auth: + # ensure you have first added these secrets + # visit app.circleci.com/settings/project/github/Dargon789/foundry/environment-variables + username: $DOCKER_HUB_USER + password: $DOCKER_HUB_PASSWORD +jobs: + web3-defi-game-project-: + + executor: my-custom-executor + steps: + - checkout + - run: | + # echo Hello, World! + +workflows: + my-custom-workflow: + jobs: + - web3-defi-game-project- diff --git a/.codesandbox/tasks.json b/.codesandbox/tasks.json new file mode 100644 index 0000000000000..b34104d5de54e --- /dev/null +++ b/.codesandbox/tasks.json @@ -0,0 +1,7 @@ +{ + // These tasks will run in order when initializing your CodeSandbox project. + "setupTasks": [], + + // These tasks can be run from CodeSandbox. Running one will open a log in the app. + "tasks": {} +} diff --git a/.deps/remix-tests/remix_accounts.sol b/.deps/remix-tests/remix_accounts.sol new file mode 100644 index 0000000000000..c1c42dc96b93e --- /dev/null +++ b/.deps/remix-tests/remix_accounts.sol @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity >=0.4.22 <0.9.0; + +library TestsAccounts { + function getAccount(uint index) pure public returns (address) { + address[15] memory accounts; + accounts[0] = 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4; + + accounts[1] = 0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2; + + accounts[2] = 0x4B20993Bc481177ec7E8f571ceCaE8A9e22C02db; + + accounts[3] = 0x78731D3Ca6b7E34aC0F824c42a7cC18A495cabaB; + + accounts[4] = 0x617F2E2fD72FD9D5503197092aC168c91465E7f2; + + accounts[5] = 0x17F6AD8Ef982297579C203069C1DbfFE4348c372; + + accounts[6] = 0x5c6B0f7Bf3E7ce046039Bd8FABdfD3f9F5021678; + + accounts[7] = 0x03C6FcED478cBbC9a4FAB34eF9f40767739D1Ff7; + + accounts[8] = 0x1aE0EA34a72D944a8C7603FfB3eC30a6669E454C; + + accounts[9] = 0x0A098Eda01Ce92ff4A4CCb7A4fFFb5A43EBC70DC; + + accounts[10] = 0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c; + + accounts[11] = 0x14723A09ACff6D2A60DcdF7aA4AFf308FDDC160C; + + accounts[12] = 0x4B0897b0513fdC7C541B6d9D7E929C4e5364D2dB; + + accounts[13] = 0x583031D1113aD414F02576BD6afaBfb302140225; + + accounts[14] = 0xdD870fA1b7C4700F2BD7f44238821C26f7392148; +return accounts[index]; + } +} diff --git a/.deps/remix-tests/remix_tests.sol b/.deps/remix-tests/remix_tests.sol new file mode 100644 index 0000000000000..b8b9960362203 --- /dev/null +++ b/.deps/remix-tests/remix_tests.sol @@ -0,0 +1,225 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity >=0.4.22 <0.9.0; + +library Assert { + + event AssertionEvent( + bool passed, + string message, + string methodName + ); + + event AssertionEventUint( + bool passed, + string message, + string methodName, + uint256 returned, + uint256 expected + ); + + event AssertionEventInt( + bool passed, + string message, + string methodName, + int256 returned, + int256 expected + ); + + event AssertionEventBool( + bool passed, + string message, + string methodName, + bool returned, + bool expected + ); + + event AssertionEventAddress( + bool passed, + string message, + string methodName, + address returned, + address expected + ); + + event AssertionEventBytes32( + bool passed, + string message, + string methodName, + bytes32 returned, + bytes32 expected + ); + + event AssertionEventString( + bool passed, + string message, + string methodName, + string returned, + string expected + ); + + event AssertionEventUintInt( + bool passed, + string message, + string methodName, + uint256 returned, + int256 expected + ); + + event AssertionEventIntUint( + bool passed, + string message, + string methodName, + int256 returned, + uint256 expected + ); + + function ok(bool a, string memory message) public returns (bool result) { + result = a; + emit AssertionEvent(result, message, "ok"); + } + + function equal(uint256 a, uint256 b, string memory message) public returns (bool result) { + result = (a == b); + emit AssertionEventUint(result, message, "equal", a, b); + } + + function equal(int256 a, int256 b, string memory message) public returns (bool result) { + result = (a == b); + emit AssertionEventInt(result, message, "equal", a, b); + } + + function equal(bool a, bool b, string memory message) public returns (bool result) { + result = (a == b); + emit AssertionEventBool(result, message, "equal", a, b); + } + + // TODO: only for certain versions of solc + //function equal(fixed a, fixed b, string message) public returns (bool result) { + // result = (a == b); + // emit AssertionEvent(result, message); + //} + + // TODO: only for certain versions of solc + //function equal(ufixed a, ufixed b, string message) public returns (bool result) { + // result = (a == b); + // emit AssertionEvent(result, message); + //} + + function equal(address a, address b, string memory message) public returns (bool result) { + result = (a == b); + emit AssertionEventAddress(result, message, "equal", a, b); + } + + function equal(bytes32 a, bytes32 b, string memory message) public returns (bool result) { + result = (a == b); + emit AssertionEventBytes32(result, message, "equal", a, b); + } + + function equal(string memory a, string memory b, string memory message) public returns (bool result) { + result = (keccak256(abi.encodePacked(a)) == keccak256(abi.encodePacked(b))); + emit AssertionEventString(result, message, "equal", a, b); + } + + function notEqual(uint256 a, uint256 b, string memory message) public returns (bool result) { + result = (a != b); + emit AssertionEventUint(result, message, "notEqual", a, b); + } + + function notEqual(int256 a, int256 b, string memory message) public returns (bool result) { + result = (a != b); + emit AssertionEventInt(result, message, "notEqual", a, b); + } + + function notEqual(bool a, bool b, string memory message) public returns (bool result) { + result = (a != b); + emit AssertionEventBool(result, message, "notEqual", a, b); + } + + // TODO: only for certain versions of solc + //function notEqual(fixed a, fixed b, string message) public returns (bool result) { + // result = (a != b); + // emit AssertionEvent(result, message); + //} + + // TODO: only for certain versions of solc + //function notEqual(ufixed a, ufixed b, string message) public returns (bool result) { + // result = (a != b); + // emit AssertionEvent(result, message); + //} + + function notEqual(address a, address b, string memory message) public returns (bool result) { + result = (a != b); + emit AssertionEventAddress(result, message, "notEqual", a, b); + } + + function notEqual(bytes32 a, bytes32 b, string memory message) public returns (bool result) { + result = (a != b); + emit AssertionEventBytes32(result, message, "notEqual", a, b); + } + + function notEqual(string memory a, string memory b, string memory message) public returns (bool result) { + result = (keccak256(abi.encodePacked(a)) != keccak256(abi.encodePacked(b))); + emit AssertionEventString(result, message, "notEqual", a, b); + } + + /*----------------- Greater than --------------------*/ + function greaterThan(uint256 a, uint256 b, string memory message) public returns (bool result) { + result = (a > b); + emit AssertionEventUint(result, message, "greaterThan", a, b); + } + + function greaterThan(int256 a, int256 b, string memory message) public returns (bool result) { + result = (a > b); + emit AssertionEventInt(result, message, "greaterThan", a, b); + } + // TODO: safely compare between uint and int + function greaterThan(uint256 a, int256 b, string memory message) public returns (bool result) { + if(b < int(0)) { + // int is negative uint "a" always greater + result = true; + } else { + result = (a > uint(b)); + } + emit AssertionEventUintInt(result, message, "greaterThan", a, b); + } + function greaterThan(int256 a, uint256 b, string memory message) public returns (bool result) { + if(a < int(0)) { + // int is negative uint "b" always greater + result = false; + } else { + result = (uint(a) > b); + } + emit AssertionEventIntUint(result, message, "greaterThan", a, b); + } + /*----------------- Lesser than --------------------*/ + function lesserThan(uint256 a, uint256 b, string memory message) public returns (bool result) { + result = (a < b); + emit AssertionEventUint(result, message, "lesserThan", a, b); + } + + function lesserThan(int256 a, int256 b, string memory message) public returns (bool result) { + result = (a < b); + emit AssertionEventInt(result, message, "lesserThan", a, b); + } + // TODO: safely compare between uint and int + function lesserThan(uint256 a, int256 b, string memory message) public returns (bool result) { + if(b < int(0)) { + // int is negative int "b" always lesser + result = false; + } else { + result = (a < uint(b)); + } + emit AssertionEventUintInt(result, message, "lesserThan", a, b); + } + + function lesserThan(int256 a, uint256 b, string memory message) public returns (bool result) { + if(a < int(0)) { + // int is negative int "a" always lesser + result = true; + } else { + result = (uint(a) < b); + } + emit AssertionEventIntUint(result, message, "lesserThan", a, b); + } +} diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000000000..53a505774ac88 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,39 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Desktop (please complete the following information):** + - OS: [e.g. iOS] + - Browser [e.g. Chrome, safari] + - Version [e.g. 22] + +**Smartphone (please complete the following information):** + - Device: [e.g. iPhone6] + - OS: [e.g. iOS8.1] + - Browser [e.g. stock browser, Safari] + - Browser [e.g. stock browser, safari] + - Version [e.g. 22] + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/custom.md b/.github/ISSUE_TEMPLATE/custom.md new file mode 100644 index 0000000000000..48d5f81fa4229 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/custom.md @@ -0,0 +1,10 @@ +--- +name: Custom issue template +about: Describe this issue template's purpose here. +title: '' +labels: '' +assignees: '' + +--- + + diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000000000..bbcbbe7d61558 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/workflows/apisec-scan.yml b/.github/workflows/apisec-scan.yml new file mode 100644 index 0000000000000..e716760284792 --- /dev/null +++ b/.github/workflows/apisec-scan.yml @@ -0,0 +1,29 @@ +name: APIsec +permissions: + contents: read + +on: + pull_request: + branches: + - main + +jobs: + scan: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Run APIsec scan + uses: apisec-inc/apisec-run-scan@025432089674a28ba8fb55f8ab06c10215e772ea + with: + apisec-username: ${{ secrets.APISEC_USERNAME }} + apisec-password: ${{ secrets.APISEC_PASSWORD }} + apisec-project: VAmPI + apisec-profile: Master + apisec-region: us-east-1 + sarif-result-file: apisec-results.sarif + apisec-email-report: true + apisec-fail-on-vuln-severity: critical + apisec-oas: false + apisec-openapi-spec-url: "https://example.com/openapi.json" diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000000000..5bf742c565e0f --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,92 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL Advanced" + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + schedule: + - cron: '25 9 * * 3' + +jobs: + analyze: + name: Analyze (${{ matrix.language }}) + # Runner size impacts CodeQL analysis time. To learn more, please see: + # - https://gh.io/recommended-hardware-resources-for-running-codeql + # - https://gh.io/supported-runners-and-hardware-resources + # - https://gh.io/using-larger-runners (GitHub.com only) + # Consider using larger runners or machines with greater resources for possible analysis time improvements. + runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} + permissions: + # required for all workflows + security-events: write + + # required to fetch internal or private CodeQL packs + packages: read + + # only required for workflows in private repositories + actions: read + contents: read + + strategy: + fail-fast: false + matrix: + include: + - language: python + build-mode: none + # CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift' + # Use `c-cpp` to analyze code written in C, C++ or both + # Use 'java-kotlin' to analyze code written in Java, Kotlin or both + # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both + # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis, + # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning. + # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how + # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ${{ matrix.language }} + build-mode: ${{ matrix.build-mode }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + + # If the analyze step fails for one of the languages you are analyzing with + # "We were unable to automatically build your code", modify the matrix above + # to set the build mode to "manual" for that language. Then modify this step + # to build your code. + # ℹ️ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + - if: matrix.build-mode == 'manual' + shell: bash + run: | + echo 'If you are using a "manual" build mode for one or more of the' \ + 'languages you are analyzing, replace this with the commands to build' \ + 'your code, for example:' + echo ' make bootstrap' + echo ' make release' + exit 1 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + with: + category: "/language:${{matrix.language}}" diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000000000..1ab3e63e39815 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,27 @@ +name: Foundry Build & Deploy +permissions: + contents: read +on: + push: + branches: [main, master] +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout repo + uses: actions/checkout@v3 + + - name: Set up Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + override: true + + - name: Build project + run: cargo build --release + + - name: Run tests + run: cargo test + + - name: Docker build + run: docker build -t foundryg-rs diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 0000000000000..5a2330e7d5d62 --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,62 @@ +name: Docker + +on: + push: + tags: ["*"] + branches: + - "main" + pull_request: + branches: ["**"] + +env: + # Hostname of your registry + REGISTRY: docker.io + # Image repository, without hostname and tag + IMAGE_NAME: ${{ github.repository }} + SHA: ${{ github.event.pull_request.head.sha || github.event.after }} + +jobs: + build: + runs-on: ubuntu-latest + permissions: + pull-requests: write + + steps: + # Authenticate to the container registry + - name: Authenticate to registry ${{ env.REGISTRY }} + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ secrets.REGISTRY_USER }} + password: ${{ secrets.REGISTRY_TOKEN }} + + - name: Setup Docker buildx + uses: docker/setup-buildx-action@v3 + + # Extract metadata (tags, labels) for Docker + - name: Extract Docker metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + labels: | + org.opencontainers.image.revision=${{ env.SHA }} + tags: | + type=edge,branch=$repo.default_branch + type=semver,pattern=v{{version}} + type=sha,prefix=,suffix=,format=short + + # Build and push Docker image with Buildx + # (don't push on PR, load instead) + - name: Build and push Docker image + id: build-and-push + uses: docker/build-push-action@v6 + with: + sbom: ${{ github.event_name != 'pull_request' }} + provenance: ${{ github.event_name != 'pull_request' }} + push: ${{ github.event_name != 'pull_request' }} + load: ${{ github.event_name == 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/.github/workflows/google.yml b/.github/workflows/google.yml new file mode 100644 index 0000000000000..1295e430ca96a --- /dev/null +++ b/.github/workflows/google.yml @@ -0,0 +1,117 @@ +# This workflow will build a docker container, publish it to Google Container +# Registry, and deploy it to GKE when there is a push to the "main" +# branch. +# +# To configure this workflow: +# +# 1. Enable the following Google Cloud APIs: +# +# - Artifact Registry (artifactregistry.googleapis.com) +# - Google Kubernetes Engine (container.googleapis.com) +# - IAM Credentials API (iamcredentials.googleapis.com) +# +# You can learn more about enabling APIs at +# https://support.google.com/googleapi/answer/6158841. +# +# 2. Ensure that your repository contains the necessary configuration for your +# Google Kubernetes Engine cluster, including deployment.yml, +# kustomization.yml, service.yml, etc. +# +# 3. Create and configure a Workload Identity Provider for GitHub: +# https://github.com/google-github-actions/auth#preferred-direct-workload-identity-federation. +# +# Depending on how you authenticate, you will need to grant an IAM principal +# permissions on Google Cloud: +# +# - Artifact Registry Administrator (roles/artifactregistry.admin) +# - Kubernetes Engine Developer (roles/container.developer) +# +# You can learn more about setting IAM permissions at +# https://cloud.google.com/iam/docs/manage-access-other-resources +# +# 5. Change the values in the "env" block to match your values. + +name: 'Build and Deploy to GKE' + +on: + push: + branches: + - '"main"' + - '"master"' + +env: + PROJECT_ID: 'my-project' # TODO: update to your Google Cloud project ID + GAR_LOCATION: 'us-central1' # TODO: update to your region + GKE_CLUSTER: 'cluster-1' # TODO: update to your cluster name + GKE_ZONE: 'us-central1-c' # TODO: update to your cluster zone + DEPLOYMENT_NAME: 'gke-test' # TODO: update to your deployment name + REPOSITORY: 'samples' # TODO: update to your Artifact Registry docker repository name + IMAGE: 'static-site' + WORKLOAD_IDENTITY_PROVIDER: 'projects/123456789/locations/global/workloadIdentityPools/my-pool/providers/my-provider' # TODO: update to your workload identity provider + +jobs: + setup-build-publish-deploy: + name: 'Setup, Build, Publish, and Deploy' + runs-on: 'ubuntu-latest' + environment: 'production' + + permissions: + contents: 'read' + id-token: 'write' + + steps: + - name: 'Checkout' + uses: 'actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332' # actions/checkout@v4 + + # Configure Workload Identity Federation and generate an access token. + # + # See https://github.com/google-github-actions/auth for more options, + # including authenticating via a JSON credentials file. + - id: 'auth' + name: 'Authenticate to Google Cloud' + uses: 'google-github-actions/auth@f112390a2df9932162083945e46d439060d66ec2' # google-github-actions/auth@v2 + with: + workload_identity_provider: '${{ env.WORKLOAD_IDENTITY_PROVIDER }}' + + # Authenticate Docker to Google Cloud Artifact Registry + - name: 'Docker Auth' + uses: 'docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567' # docker/login-action@v3 + with: + username: 'oauth2accesstoken' + password: '${{ steps.auth.outputs.auth_token }}' + registry: '${{ env.GAR_LOCATION }}-docker.pkg.dev' + + # Get the GKE credentials so we can deploy to the cluster + - name: 'Set up GKE credentials' + uses: 'google-github-actions/get-gke-credentials@6051de21ad50fbb1767bc93c11357a49082ad116' # google-github-actions/get-gke-credentials@v2 + with: + cluster_name: '${{ env.GKE_CLUSTER }}' + location: '${{ env.GKE_ZONE }}' + + # Build the Docker image + - name: 'Build and push Docker container' + run: |- + DOCKER_TAG="${GAR_LOCATION}-docker.pkg.dev/${PROJECT_ID}/${REPOSITORY}/${IMAGE}:${GITHUB_SHA}" + + docker build \ + --tag "${DOCKER_TAG}" \ + --build-arg GITHUB_SHA="${GITHUB_SHA}" \ + --build-arg GITHUB_REF="${GITHUB_REF}" \ + . + + docker push "${DOCKER_TAG}" + + # Set up kustomize + - name: 'Set up Kustomize' + run: |- + curl -sfLo kustomize https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize%2Fv5.4.3/kustomize_v5.4.3_linux_amd64.tar.gz + chmod u+x ./kustomize + + # Deploy the Docker image to the GKE cluster + - name: 'Deploy to GKE' + run: |- + # replacing the image name in the k8s template + ./kustomize edit set image LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE:TAG=$GAR_LOCATION-docker.pkg.dev/$PROJECT_ID/$REPOSITORY/$IMAGE:$GITHUB_SHA + ./kustomize build . | kubectl apply -f - + kubectl rollout status deployment/$DEPLOYMENT_NAME + kubectl get services -o wide diff --git a/.github/workflows/npm.yml b/.github/workflows/npm.yml index 7bb1ad13a42db..6347fe0fd59d2 100644 --- a/.github/workflows/npm.yml +++ b/.github/workflows/npm.yml @@ -233,9 +233,46 @@ jobs: PLATFORM='${{ matrix.os }}' ARCH='${{ matrix.arch }}' + # Basic validation of matrix-derived values to avoid path manipulation + case "$TOOL" in + (*[!a-zA-Z0-9_-]*|'') echo "ERROR: Invalid TOOL value: $TOOL" >&2; exit 1 ;; + esac + case "$PLATFORM" in + (*[!a-zA-Z0-9_-]*|'') echo "ERROR: Invalid PLATFORM value: $PLATFORM" >&2; exit 1 ;; + esac + case "$ARCH" in + (*[!a-zA-Z0-9_-]*|'') echo "ERROR: Invalid ARCH value: $ARCH" >&2; exit 1 ;; + esac + PACKAGE_DIR="./@foundry-rs/${TOOL}-${PLATFORM}-${ARCH}" + echo "Preparing to publish package from: $PACKAGE_DIR" + + if [[ ! -d "$PACKAGE_DIR" ]]; then + echo "ERROR: Package directory does not exist: $PACKAGE_DIR" >&2 + exit 1 + fi + + # Resolve to an absolute path and ensure it stays within ./@foundry-rs + ABS_PACKAGE_DIR="$(realpath "$PACKAGE_DIR")" + ABS_EXPECTED_ROOT="$(realpath "./@foundry-rs")" + case "$ABS_PACKAGE_DIR" in + "$ABS_EXPECTED_ROOT"/*) ;; + *) + echo "ERROR: Resolved package directory is outside expected root:" >&2 + echo " ABS_PACKAGE_DIR=$ABS_PACKAGE_DIR" >&2 + echo " ABS_EXPECTED_ROOT=$ABS_EXPECTED_ROOT" >&2 + exit 1 + ;; + esac + ls -la "$PACKAGE_DIR" + # Minimal sanity check: require a package.json before publishing + if [[ ! -f "$PACKAGE_DIR/package.json" ]]; then + echo "ERROR: package.json not found in $PACKAGE_DIR; refusing to publish." >&2 + exit 1 + fi + bun ./scripts/publish.mjs "$PACKAGE_DIR" echo "Published @foundry-rs/${TOOL}-${PLATFORM}-${ARCH}" diff --git a/.github/workflows/snyk-container.yml b/.github/workflows/snyk-container.yml new file mode 100644 index 0000000000000..f07df9c75c8d1 --- /dev/null +++ b/.github/workflows/snyk-container.yml @@ -0,0 +1,55 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. +# +# A sample workflow which checks out the code, builds a container +# image using Docker and scans that image for vulnerabilities using +# Snyk. The results are then uploaded to GitHub Security Code Scanning +# +# For more examples, including how to limit scans to only high-severity +# issues, monitor images for newly disclosed vulnerabilities in Snyk and +# fail PR checks for new vulnerabilities, see https://github.com/snyk/actions/ + +name: Snyk Container + +on: + push: + branches: [ "master" ] + pull_request: + # The branches below must be a subset of the branches above + branches: [ "master" ] + schedule: + - cron: '30 10 * * 1' + +permissions: + contents: read + +jobs: + snyk: + permissions: + contents: read # for actions/checkout to fetch code + security-events: write # for github/codeql-action/upload-sarif to upload SARIF results + actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + - name: Build a Docker image + run: docker build -t your/image-to-test . + - name: Run Snyk to check Docker image for vulnerabilities + # Snyk can be used to break the build when it detects vulnerabilities. + # In this case we want to upload the issues to GitHub Code Scanning + continue-on-error: true + uses: snyk/actions/docker@9adf32b1121593767fc3c057af55b55db032dc04 + env: + # In order to use the Snyk Action you will need to have a Snyk API token. + # More details in https://github.com/snyk/actions#getting-your-snyk-token + # or you can signup for free at https://snyk.io/login + SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} + with: + image: your/image-to-test + args: --file=Dockerfile + - name: Upload result to GitHub Code Scanning + uses: github/codeql-action/upload-sarif@v4 + with: + sarif_file: snyk.sarif diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000000..b1269653d9c6f --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "counter/lib/forge-std"] + path = counter/lib/forge-std + url = https://github.com/foundry-rs/forge-std +[submodule "counter/lib/openzeppelin-contracts"] + path = counter/lib/openzeppelin-contracts + url = https://github.com/OpenZeppelin/openzeppelin-contracts diff --git a/benches/src/lib.rs b/benches/src/lib.rs index d50f88ae2bd63..55bbd9762b1d9 100644 --- a/benches/src/lib.rs +++ b/benches/src/lib.rs @@ -130,10 +130,20 @@ impl BenchmarkProject { for entry in std::fs::read_dir(&root_path)? { let entry = entry?; let path = entry.path(); - if path.is_dir() { - std::fs::remove_dir_all(&path).ok(); + // Canonicalize the entry to prevent directory traversal + let canon = match path.canonicalize() { + Ok(p) => p, + Err(_) => continue, // Skip if unable to canonicalize + }; + // Ensure canonicalized path stays strictly within root_path (TempProject root) + if !canon.starts_with(&root_path) { + sh_eprintln!("⚠️ Skipping suspicious path during cleanup: {:?}", canon); + continue; + } + if canon.is_dir() { + std::fs::remove_dir_all(&canon).ok(); } else { - std::fs::remove_file(&path).ok(); + std::fs::remove_file(&canon).ok(); } } diff --git a/counter/.github/workflows/test.yml b/counter/.github/workflows/test.yml new file mode 100644 index 0000000000000..34a4a527be6f9 --- /dev/null +++ b/counter/.github/workflows/test.yml @@ -0,0 +1,43 @@ +name: CI + +on: + push: + pull_request: + workflow_dispatch: + +env: + FOUNDRY_PROFILE: ci + +jobs: + check: + strategy: + fail-fast: true + + name: Foundry project + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + + - name: Show Forge version + run: | + forge --version + + - name: Run Forge fmt + run: | + forge fmt --check + id: fmt + + - name: Run Forge build + run: | + forge build --sizes + id: build + + - name: Run Forge tests + run: | + forge test -vvv + id: test diff --git a/counter/.gitignore b/counter/.gitignore new file mode 100644 index 0000000000000..85198aaa55b84 --- /dev/null +++ b/counter/.gitignore @@ -0,0 +1,14 @@ +# Compiler files +cache/ +out/ + +# Ignores development broadcast logs +!/broadcast +/broadcast/*/31337/ +/broadcast/**/dry-run/ + +# Docs +docs/ + +# Dotenv file +.env diff --git a/counter/README.md b/counter/README.md new file mode 100644 index 0000000000000..679a7f4518035 --- /dev/null +++ b/counter/README.md @@ -0,0 +1,66 @@ +## Foundry + +**Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.** + +Foundry consists of: + +- **Forge**: Ethereum testing framework (like Truffle, Hardhat and DappTools). +- **Cast**: Swiss army knife for interacting with EVM smart contracts, sending transactions and getting chain data. +- **Anvil**: Local Ethereum node, akin to Ganache, Hardhat Network. +- **Chisel**: Fast, utilitarian, and verbose Solidity REPL. + +## Documentation + +https://book.getfoundry.sh/ + +## Usage + +### Build + +```shell +$ forge build +``` + +### Test + +```shell +$ forge test +``` + +### Format + +```shell +$ forge fmt +``` + +### Gas Snapshots + +```shell +$ forge snapshot +``` + +### Anvil + +```shell +$ anvil +``` + +### Deploy + +```shell +$ forge script script/Counter.s.sol:CounterScript --rpc-url --private-key +``` + +### Cast + +```shell +$ cast +``` + +### Help + +```shell +$ forge --help +$ anvil --help +$ cast --help +``` diff --git a/counter/foundry.toml b/counter/foundry.toml new file mode 100644 index 0000000000000..25b918f9c9a96 --- /dev/null +++ b/counter/foundry.toml @@ -0,0 +1,6 @@ +[profile.default] +src = "src" +out = "out" +libs = ["lib"] + +# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options diff --git a/counter/lib/forge-std b/counter/lib/forge-std new file mode 160000 index 0000000000000..3b20d60d14b34 --- /dev/null +++ b/counter/lib/forge-std @@ -0,0 +1 @@ +Subproject commit 3b20d60d14b343ee4f908cb8079495c07f5e8981 diff --git a/counter/lib/openzeppelin-contracts b/counter/lib/openzeppelin-contracts new file mode 160000 index 0000000000000..ca7a4e39de086 --- /dev/null +++ b/counter/lib/openzeppelin-contracts @@ -0,0 +1 @@ +Subproject commit ca7a4e39de0860bbaadf95824207886e6de9fa64 diff --git a/counter/script/Counter.s.sol b/counter/script/Counter.s.sol new file mode 100644 index 0000000000000..cdc1fe9a1ba25 --- /dev/null +++ b/counter/script/Counter.s.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +import {Script, console} from "forge-std/Script.sol"; +import {Counter} from "../src/Counter.sol"; + +contract CounterScript is Script { + Counter public counter; + + function setUp() public {} + + function run() public { + vm.startBroadcast(); + + counter = new Counter(); + + vm.stopBroadcast(); + } +} diff --git a/counter/src/Counter.sol b/counter/src/Counter.sol new file mode 100644 index 0000000000000..aded7997b0c35 --- /dev/null +++ b/counter/src/Counter.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +contract Counter { + uint256 public number; + + function setNumber(uint256 newNumber) public { + number = newNumber; + } + + function increment() public { + number++; + } +} diff --git a/counter/test/Counter.t.sol b/counter/test/Counter.t.sol new file mode 100644 index 0000000000000..54b724f7ae766 --- /dev/null +++ b/counter/test/Counter.t.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +import {Test, console} from "forge-std/Test.sol"; +import {Counter} from "../src/Counter.sol"; + +contract CounterTest is Test { + Counter public counter; + + function setUp() public { + counter = new Counter(); + counter.setNumber(0); + } + + function test_Increment() public { + counter.increment(); + assertEq(counter.number(), 1); + } + + function testFuzz_SetNumber(uint256 x) public { + counter.setNumber(x); + assertEq(counter.number(), x); + } +} diff --git a/crates/cast/src/cmd/run.rs b/crates/cast/src/cmd/run.rs index 492ce360e7c2e..0999aa55ec495 100644 --- a/crates/cast/src/cmd/run.rs +++ b/crates/cast/src/cmd/run.rs @@ -31,7 +31,7 @@ use foundry_evm::{ utils::configure_tx_env, }; use futures::TryFutureExt; -use revm::DatabaseRef; +use revm::{DatabaseRef, primitives::hardfork::SpecId}; /// CLI arguments for `cast run`. #[derive(Clone, Debug, Parser)] @@ -183,6 +183,8 @@ impl RunArgs { env.evm_env.cfg_env.limit_contract_code_size = None; env.evm_env.block_env.number = U256::from(tx_block_number); + let mut parent_beacon_block_root = None; + if let Some(block) = &block { env.evm_env.block_env.timestamp = U256::from(block.header.timestamp); env.evm_env.block_env.beneficiary = block.header.beneficiary; @@ -191,6 +193,10 @@ impl RunArgs { env.evm_env.block_env.basefee = block.header.base_fee_per_gas.unwrap_or_default(); env.evm_env.block_env.gas_limit = block.header.gas_limit; + if env.evm_env.cfg_env.spec >= SpecId::CANCUN { + parent_beacon_block_root = block.header.parent_beacon_block_root; + } + // TODO: we need a smarter way to map the block to the corresponding evm_version for // commonly used chains if evm_version.is_none() { @@ -223,6 +229,12 @@ impl RunArgs { create2_deployer, None, )?; + + if let Some(parent_beacon_block_root) = parent_beacon_block_root { + let timestamp: u64 = env.evm_env.block_env.timestamp.try_into().wrap_err("failed to convert block timestamp to u64")?; + executor.process_beacon_block_root(timestamp, parent_beacon_block_root)?; + } + let mut env = Env::new_with_spec_id( env.evm_env.cfg_env.clone(), env.evm_env.block_env.clone(), diff --git a/crates/cast/tests/cli/main.rs b/crates/cast/tests/cli/main.rs index a9147e2e284ff..7aafdceb8a402 100644 --- a/crates/cast/tests/cli/main.rs +++ b/crates/cast/tests/cli/main.rs @@ -2998,6 +2998,34 @@ Traces: "#]]); }); +// tests that displays a sample beacon block traces in Cancun +// https://github.com/foundry-rs/foundry/issues/12435 +casttest!(test_beacon_block_root_in_cancun, |prj, cmd| { + prj.clear(); + let eth_rpc_url = next_http_rpc_endpoint(); + cmd.args([ + "run", + "0xae290fe8c89c3e83dff20eeb2b8e3261bcdce0d66441c7056918dfb5fafe6d96", + "--rpc-url", + eth_rpc_url.as_str(), + ]) + .assert_success() + .stdout_eq(str![[r#" +Executing previous transactions from the block. +Traces: + [45054] 0xB731392c0EB5BF2092f9f7B520DA551f70Ea9131::Claim{value: 46698476594582387}() + ├─ [4320] 0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02::00000000(00000000000000000000000000000000000000000000000069091d4b) [staticcall] + │ └─ ← [Return] 0x70c7855161ec07af782df915fb3e81702df40f34972da3d740cdfc132ac926f6 + ├─ emit NvStuck(param0: 0x6e6C36B970f8862bA3F148DEdAB8F98f5ed8b426, param1: 46698476594582387 [4.669e16], param2: 1762205003 [1.762e9]) + └─ ← [Stop] + + +Transaction successfully executed. +[GAS] + +"#]]); +}); + // tests that displays a sample contract artifact // casttest!(flaky_fetch_artifact_from_etherscan, |_prj, cmd| { diff --git a/crates/cli/src/utils/suggestions.rs b/crates/cli/src/utils/suggestions.rs index a675ccae963c9..8f6d7f3cde092 100644 --- a/crates/cli/src/utils/suggestions.rs +++ b/crates/cli/src/utils/suggestions.rs @@ -1,4 +1,5 @@ //! Helper functions for suggesting alternative values for a possibly erroneous user input. +use std::cmp::Ordering; /// Filters multiple strings from a given list of possible values which are similar /// to the passed in value `v` within a certain confidence by least confidence. @@ -16,7 +17,7 @@ where .map(|pv| (strsim::jaro_winkler(v, pv.as_ref()), pv.as_ref().to_owned())) .filter(|(similarity, _)| *similarity > 0.8) .collect(); - candidates.sort_by(|a, b| a.0.total_cmp(&b.0)); + candidates.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap_or(Ordering::Equal)); candidates.into_iter().map(|(_, pv)| pv).collect() } diff --git a/crates/common/src/contracts.rs b/crates/common/src/contracts.rs index 06b2c29945417..f079d0f4fbf3d 100644 --- a/crates/common/src/contracts.rs +++ b/crates/common/src/contracts.rs @@ -239,7 +239,7 @@ impl ContractsByArtifact { None } }) - .min_by(|(score1, _), (score2, _)| score1.total_cmp(score2)) + .min_by(|(score1, _), (score2, _)| score1.partial_cmp(score2).unwrap_or(std::cmp::Ordering::Equal)) .map(|(_, data)| data) } diff --git a/crates/doc/src/parser/comment.rs b/crates/doc/src/parser/comment.rs index 431bf70df88f5..69f529c3eb6a2 100644 --- a/crates/doc/src/parser/comment.rs +++ b/crates/doc/src/parser/comment.rs @@ -155,6 +155,12 @@ impl From> for Comments { } } +impl From> for Comments { + fn from(value: Vec) -> Self { + Self(value) + } +} + /// The collection of references to natspec [Comment] items. #[derive(Debug, Default, PartialEq, Deref)] pub struct CommentsRef<'a>(Vec<&'a Comment>); diff --git a/crates/doc/src/writer/as_doc.rs b/crates/doc/src/writer/as_doc.rs index a215a95b581c7..455cd4082bb61 100644 --- a/crates/doc/src/writer/as_doc.rs +++ b/crates/doc/src/writer/as_doc.rs @@ -1,12 +1,11 @@ use crate::{ - CONTRACT_INHERITANCE_ID, CommentTag, Comments, CommentsRef, DEPLOYMENTS_ID, Document, - GIT_SOURCE_ID, INHERITDOC_ID, Markdown, PreprocessorOutput, - document::{DocumentContent, read_context}, - helpers::function_signature, + document::{read_context, DocumentContent}, parser::ParseSource, - solang_ext::SafeUnwrap, writer::BufWriter, + CommentTag, Comments, CommentsRef, Document, Markdown, PreprocessorOutput, + CONTRACT_INHERITANCE_ID, DEPLOYMENTS_ID, GIT_SOURCE_ID, INHERITDOC_ID, }; +use forge_fmt::solang_ext::SafeUnwrap; use itertools::Itertools; use solang_parser::pt::{Base, FunctionDefinition}; use std::path::Path; @@ -63,7 +62,7 @@ impl AsDoc for CommentsRef<'_> { // Write dev tags let devs = self.include_tag(CommentTag::Dev); for d in devs.iter() { - writer.write_dev_content(&d.value)?; + writer.write_italic(&d.value)?; writer.writeln()?; } @@ -107,7 +106,16 @@ impl AsDoc for Document { for item in items { let func = item.as_function().unwrap(); - let heading = function_signature(func).replace(',', ", "); + let mut heading = item.source.ident(); + if !func.params.is_empty() { + heading.push_str(&format!( + "({})", + func.params + .iter() + .map(|p| p.1.as_ref().map(|p| p.ty.to_string()).unwrap_or_default()) + .join(", ") + )); + } writer.write_heading(&heading)?; writer.write_section(&item.comments, &item.code)?; } @@ -226,7 +234,15 @@ impl AsDoc for Document { writer.write_subtitle("Enums")?; enums.into_iter().try_for_each(|(item, comments, code)| { writer.write_heading(&item.name.safe_unwrap().name)?; - writer.write_section(comments, code)?; + + let filtered_comments: Comments = (*comments) + .iter() + .filter(|c| c.tag != CommentTag::Custom("variant".to_string())) + .cloned() + .collect::>() + .into(); + + writer.write_section(&filtered_comments, code)?; writer.try_write_variant_table(item, comments) })?; } @@ -292,10 +308,9 @@ impl Document { comments: &Comments, code: &str, ) -> Result<(), std::fmt::Error> { - let func_sign = function_signature(func); let func_name = func.name.as_ref().map_or(func.ty.to_string(), |n| n.name.to_owned()); let comments = - comments.merge_inheritdoc(&func_sign, read_context!(self, INHERITDOC_ID, Inheritdoc)); + comments.merge_inheritdoc(&func_name, read_context!(self, INHERITDOC_ID, Inheritdoc)); // Write function name writer.write_heading(&func_name)?; diff --git a/crates/doc/src/writer/buf_writer.rs b/crates/doc/src/writer/buf_writer.rs index a62dff3f21582..e5dfbbaadce25 100644 --- a/crates/doc/src/writer/buf_writer.rs +++ b/crates/doc/src/writer/buf_writer.rs @@ -1,4 +1,4 @@ -use crate::{AsDoc, CommentTag, Comments, Deployment, Markdown, writer::traits::ParamLike}; +use crate::{writer::traits::ParamLike, AsDoc, CommentTag, Comments, Deployment, Markdown}; use itertools::Itertools; use solang_parser::pt::{ EnumDefinition, ErrorParameter, EventParameter, Parameter, VariableDeclaration, @@ -89,17 +89,6 @@ impl BufWriter { writeln!(self.buf, "{}", Markdown::Italic(text)) } - /// Writes dev content to the buffer, handling markdown lists properly. - /// If the content contains markdown lists, it formats them correctly. - /// Otherwise, it writes the content in italics. - pub fn write_dev_content(&mut self, text: &str) -> fmt::Result { - for line in text.lines() { - writeln!(self.buf, "{line}")?; - } - - Ok(()) - } - /// Writes bold text to the buffer formatted as [Markdown::Bold]. pub fn write_bold(&mut self, text: &str) -> fmt::Result { writeln!(self.buf, "{}", Markdown::Bold(text)) @@ -202,7 +191,8 @@ impl BufWriter { params: &EnumDefinition, comments: &Comments, ) -> fmt::Result { - let comments = comments.include_tags(&[CommentTag::Param]); + let comments = + comments.include_tags(&[CommentTag::Param, CommentTag::Custom("variant".to_string())]); // There is nothing to write. if comments.is_empty() { @@ -215,7 +205,7 @@ impl BufWriter { self.write_piped(&VARIANTS_TABLE_HEADERS.join("|"))?; self.write_piped(&VARIANTS_TABLE_SEPARATOR)?; - for value in ¶ms.values { + for value in params.values.iter() { let param_name = value.as_ref().map(|v| v.name.clone()); let comment = param_name.as_ref().and_then(|name| { @@ -223,7 +213,7 @@ impl BufWriter { }); let row = [ - Markdown::Code(¶m_name.unwrap_or("".to_string())).as_doc()?, + Markdown::Code(param_name.as_deref().unwrap_or("")).as_doc()?, comment.unwrap_or_default().replace('\n', " "), ]; self.write_piped(&row.join("|"))?; diff --git a/crates/evm/evm/src/executors/trace.rs b/crates/evm/evm/src/executors/trace.rs index d951dde0d6663..7b63c019e848c 100644 --- a/crates/evm/evm/src/executors/trace.rs +++ b/crates/evm/evm/src/executors/trace.rs @@ -2,7 +2,7 @@ use crate::{ Env, executors::{Executor, ExecutorBuilder}, }; -use alloy_primitives::{Address, U256, map::HashMap}; +use alloy_primitives::{Address, FixedBytes, U256, address, map::HashMap}; use alloy_rpc_types::state::StateOverride; use eyre::Context; use foundry_compilers::artifacts::EvmVersion; @@ -92,6 +92,32 @@ impl TracingExecutor { let chain = env.tx.chain_id.unwrap().into(); Ok((env, fork, chain, networks)) } + + /// Processes the beacon block root by storing it in the appropriate storage slots. + pub fn process_beacon_block_root( + &mut self, + block_timestamp: u64, + beacon_root: FixedBytes<32>, + ) -> eyre::Result<()> { + const BEACON_ROOTS_ADDRESS: Address = address!("000F3df6D732807Ef1319fB7B8bB8522d0Beac02"); + const HISTORY_BUFFER_LENGTH: u64 = 8192; + + let timestamp_index = block_timestamp % HISTORY_BUFFER_LENGTH; + let root_index = timestamp_index + HISTORY_BUFFER_LENGTH; + + let timestamp_slot = U256::from(timestamp_index); + let root_slot = U256::from(root_index); + + self.set_storage_slot(BEACON_ROOTS_ADDRESS, timestamp_slot, U256::from(block_timestamp))?; + + self.set_storage_slot( + BEACON_ROOTS_ADDRESS, + root_slot, + U256::from_be_bytes(beacon_root.into()), + )?; + + Ok(()) + } } impl Deref for TracingExecutor { diff --git a/crates/forge/Cargo.toml b/crates/forge/Cargo.toml index cd552853cfcff..2142a87c5cbd4 100644 --- a/crates/forge/Cargo.toml +++ b/crates/forge/Cargo.toml @@ -62,6 +62,7 @@ alloy-rpc-types.workspace = true alloy-serde.workspace = true alloy-signer.workspace = true alloy-transport.workspace = true +alloy-hardforks.workspace = true revm.workspace = true diff --git a/crates/forge/tests/cli/test_optimizer.rs b/crates/forge/tests/cli/test_optimizer.rs index c744ff6457596..223549b08b048 100644 --- a/crates/forge/tests/cli/test_optimizer.rs +++ b/crates/forge/tests/cli/test_optimizer.rs @@ -1374,7 +1374,6 @@ Compiling 21 files with [..] }); // Test preprocessed contracts with decode internal fns. -#[cfg(not(feature = "isolate-by-default"))] forgetest_init!(preprocess_contract_with_decode_internal, |prj, cmd| { prj.initialize_default_contracts(); prj.update_config(|config| { diff --git a/crates/lint/src/linter.rs b/crates/lint/src/linter.rs new file mode 100644 index 0000000000000..2c11e0222a286 --- /dev/null +++ b/crates/lint/src/linter.rs @@ -0,0 +1,129 @@ +use foundry_compilers::Language; +use foundry_config::lint::Severity; +use solar_ast::{visit::Visit, Expr, ItemFunction, ItemStruct, VariableDefinition}; +use solar_interface::{ + data_structures::Never, + diagnostics::{DiagBuilder, DiagId, MultiSpan}, + Session, Span, +}; +use std::{ops::ControlFlow, path::PathBuf}; + +/// Trait representing a generic linter for analyzing and reporting issues in smart contract source +/// code files. A linter can be implemented for any smart contract language supported by Foundry. +/// +/// # Type Parameters +/// +/// - `Language`: Represents the target programming language. Must implement the [`Language`] trait. +/// - `Lint`: Represents the types of lints performed by the linter. Must implement the [`Lint`] +/// trait. +/// +/// # Required Methods +/// +/// - `lint`: Scans the provided source files emitting a daignostic for lints found. +pub trait Linter: Send + Sync + Clone { + type Language: Language; + type Lint: Lint; + + fn lint(&self, input: &[PathBuf]); +} + +pub trait Lint { + fn id(&self) -> &'static str; + fn severity(&self) -> Severity; + fn description(&self) -> &'static str; + fn help(&self) -> &'static str; +} + +pub struct LintContext<'s> { + sess: &'s Session, + desc: bool, +} + +impl<'s> LintContext<'s> { + pub fn new(sess: &'s Session, with_description: bool) -> Self { + Self { sess, desc: with_description } + } + + // Helper method to emit diagnostics easily from passes + pub fn emit(&self, lint: &'static L, span: Span) { + let desc = if self.desc { lint.description() } else { "" }; + let diag: DiagBuilder<'_, ()> = self + .sess + .dcx + .diag(lint.severity().into(), desc) + .code(DiagId::new_str(lint.id())) + .span(MultiSpan::from_span(span)) + .help(lint.help()); + + diag.emit(); + } +} + +/// Trait for lints that operate directly on the AST. +/// Its methods mirror `solar_ast::visit::Visit`, with the addition of `LintCotext`. +pub trait EarlyLintPass<'ast>: Send + Sync { + fn check_expr(&mut self, _ctx: &LintContext<'_>, _expr: &'ast Expr<'ast>) {} + fn check_item_struct(&mut self, _ctx: &LintContext<'_>, _struct: &'ast ItemStruct<'ast>) {} + fn check_item_function(&mut self, _ctx: &LintContext<'_>, _func: &'ast ItemFunction<'ast>) {} + fn check_variable_definition( + &mut self, + _ctx: &LintContext<'_>, + _var: &'ast VariableDefinition<'ast>, + ) { + } + + // TODO: Add methods for each required AST node type +} + +/// Visitor struct for `EarlyLintPass`es +pub struct EarlyLintVisitor<'a, 's, 'ast> { + pub ctx: &'a LintContext<'s>, + pub passes: &'a mut [Box + 's>], +} + +impl<'s, 'ast> Visit<'ast> for EarlyLintVisitor<'_, 's, 'ast> +where + 's: 'ast, +{ + type BreakValue = Never; + + fn visit_expr(&mut self, expr: &'ast Expr<'ast>) -> ControlFlow { + for pass in self.passes.iter_mut() { + pass.check_expr(self.ctx, expr) + } + self.walk_expr(expr) + } + + fn visit_variable_definition( + &mut self, + var: &'ast VariableDefinition<'ast>, + ) -> ControlFlow { + for pass in self.passes.iter_mut() { + pass.check_variable_definition(self.ctx, var) + } + self.walk_variable_definition(var) + } + + fn visit_item_struct( + &mut self, + strukt: &'ast ItemStruct<'ast>, + ) -> ControlFlow { + for pass in self.passes.iter_mut() { + pass.check_item_struct(self.ctx, strukt) + } + self.walk_item_struct(strukt) + } + + fn visit_item_function( + &mut self, + func: &'ast ItemFunction<'ast>, + ) -> ControlFlow { + for pass in self.passes.iter_mut() { + pass.check_item_function(self.ctx, func) + } + self.walk_item_function(func) + } + + // TODO: Add methods for each required AST node type, mirroring `solar_ast::visit::Visit` method + // sigs + adding `LintContext` +} diff --git a/crates/lint/src/sol/gas/keccak.rs b/crates/lint/src/sol/gas/keccak.rs index cb942510bbb49..7316f4c4239b7 100644 --- a/crates/lint/src/sol/gas/keccak.rs +++ b/crates/lint/src/sol/gas/keccak.rs @@ -1,103 +1,27 @@ use super::AsmKeccak256; use crate::{ - linter::{LateLintPass, LintContext}, + declare_forge_lint, + linter::EarlyLintPass, sol::{Severity, SolLint}, }; -use solar::{ - ast::{self as ast, Span}, - interface::kw, - sema::hir::{self}, -}; +use solar_ast::{Expr, ExprKind}; +use solar_interface::kw; declare_forge_lint!( ASM_KECCAK256, Severity::Gas, "asm-keccak256", - "use of inefficient hashing mechanism; consider using inline assembly" + "hash using inline assembly to save gas" ); -impl<'hir> LateLintPass<'hir> for AsmKeccak256 { - fn check_stmt( - &mut self, - ctx: &LintContext, - hir: &'hir hir::Hir<'hir>, - stmt: &'hir hir::Stmt<'hir>, - ) { - let check_expr_and_emit_lint = - |expr: &'hir hir::Expr<'hir>, assign: Option, is_return: bool| { - if let Some(hash_arg) = extract_keccak256_arg(expr) { - self.emit_lint( - ctx, - hir, - stmt.span, - expr, - hash_arg, - AsmContext { _assign: assign, _is_return: is_return }, - ); - } - }; - - match stmt.kind { - hir::StmtKind::DeclSingle(var_id) => { - let var = hir.variable(var_id); - if let Some(init) = var.initializer { - // Constants should be optimized by the compiler, so no gas savings apply. - if !matches!(var.mutability, Some(hir::VarMut::Constant)) { - check_expr_and_emit_lint(init, var.name, false); - } +impl<'ast> EarlyLintPass<'ast> for AsmKeccak256 { + fn check_expr(&mut self, ctx: &crate::linter::LintContext<'_>, expr: &'ast Expr<'ast>) { + if let ExprKind::Call(expr, _) = &expr.kind { + if let ExprKind::Ident(ident) = &expr.kind { + if ident.name == kw::Keccak256 { + ctx.emit(&ASM_KECCAK256, expr.span); } } - // Expressions that don't (directly) assign to a variable - hir::StmtKind::Expr(expr) - | hir::StmtKind::Emit(expr) - | hir::StmtKind::Revert(expr) - | hir::StmtKind::DeclMulti(_, expr) - | hir::StmtKind::If(expr, ..) => check_expr_and_emit_lint(expr, None, false), - hir::StmtKind::Return(Some(expr)) => check_expr_and_emit_lint(expr, None, true), - _ => (), } } } - -impl AsmKeccak256 { - /// Emits lints (when possible with fix suggestions) for inefficient `keccak256` calls. - fn emit_lint( - &self, - ctx: &LintContext, - _hir: &hir::Hir<'_>, - _stmt_span: Span, - call: &hir::Expr<'_>, - _hash: &hir::Expr<'_>, - _asm_ctx: AsmContext, - ) { - ctx.emit(&ASM_KECCAK256, call.span); - } -} - -/// If the expression is a call to `keccak256` with one argument, returns that argument. -fn extract_keccak256_arg<'hir>(expr: &'hir hir::Expr<'hir>) -> Option<&'hir hir::Expr<'hir>> { - let hir::ExprKind::Call( - callee, - hir::CallArgs { kind: hir::CallArgsKind::Unnamed(args), .. }, - .., - ) = &expr.kind - else { - return None; - }; - - let is_keccak = if let hir::ExprKind::Ident([hir::Res::Builtin(builtin)]) = callee.kind { - matches!(builtin.name(), kw::Keccak256) - } else { - return None; - }; - - if is_keccak && args.len() == 1 { Some(&args[0]) } else { None } -} - -// -- HELPER FUNCTIONS AND STRUCTS ---------------------------------------------------------------- - -#[derive(Debug, Clone, Copy)] -struct AsmContext { - _assign: Option, - _is_return: bool, -} diff --git a/crates/script-sequence/src/sequence.rs b/crates/script-sequence/src/sequence.rs index 5da88735a70ec..56b7c6b36f79c 100644 --- a/crates/script-sequence/src/sequence.rs +++ b/crates/script-sequence/src/sequence.rs @@ -12,7 +12,7 @@ use std::{ path::PathBuf, time::{Duration, SystemTime, UNIX_EPOCH}, }; - +# pub const DRY_RUN_DIR: &str = "dry-run"; #[derive(Clone, Serialize, Deserialize)] @@ -20,7 +20,7 @@ pub struct NestedValue { pub internal_type: String, pub value: String, } - +# /// Helper that saves the transactions sequence and its state on which transactions have been /// broadcasted #[derive(Clone, Default, Serialize, Deserialize)] @@ -148,7 +148,7 @@ impl ScriptSequence { pub fn add_receipt(&mut self, receipt: AnyTransactionReceipt) { self.receipts.push(receipt); } - + # /// Sorts all receipts with ascending transaction index pub fn sort_receipts(&mut self) { self.receipts.sort_by_key(|r| (r.block_number, r.transaction_index)); @@ -164,7 +164,7 @@ impl ScriptSequence { pub fn remove_pending(&mut self, tx_hash: TxHash) { self.pending.retain(|element| element != &tx_hash); } - + # /// Gets paths in the formats /// `./broadcast/[contract_filename]/[chain_id]/[sig]-[timestamp].json` and /// `./cache/[contract_filename]/[chain_id]/[sig]-[timestamp].json`. @@ -219,7 +219,7 @@ impl ScriptSequence { .for_each(|(i, tx)| tx.rpc.clone_from(&sensitive.transactions[i].rpc)); } } - +# /// Converts the `sig` argument into the corresponding file path. /// /// This accepts either the signature of the function or the raw calldata. diff --git a/crates/script/src/simulate.rs b/crates/script/src/simulate.rs index ab57786398428..0b2be58ca30d2 100644 --- a/crates/script/src/simulate.rs +++ b/crates/script/src/simulate.rs @@ -9,7 +9,6 @@ use crate::{ execute::{ExecutionArtifacts, ExecutionData}, sequence::get_commit_hash, }; -use alloy_chains::NamedChain; use alloy_network::TransactionBuilder; use alloy_primitives::{Address, TxKind, U256, map::HashMap, utils::format_units}; use dialoguer::Confirm; @@ -352,12 +351,6 @@ impl FilledTransactionsState { for (rpc, total_gas) in total_gas_per_rpc { let provider_info = manager.get(&rpc).expect("provider is set."); - // Get the native token symbol for the chain using NamedChain - let token_symbol = NamedChain::try_from(provider_info.chain) - .unwrap_or_default() - .native_currency_symbol() - .unwrap_or("ETH"); - // We don't store it in the transactions, since we want the most updated value. // Right before broadcasting. let per_gas = if let Some(gas_price) = self.args.with_gas_price { @@ -381,7 +374,7 @@ impl FilledTransactionsState { sh_println!("\nEstimated gas price: {} gwei", estimated_gas_price)?; sh_println!("\nEstimated total gas used for script: {total_gas}")?; - sh_println!("\nEstimated amount required: {estimated_amount} {token_symbol}")?; + sh_println!("\nEstimated amount required: {estimated_amount} ETH",)?; sh_println!("\n==========================")?; } else { sh_println!( @@ -391,7 +384,6 @@ impl FilledTransactionsState { "estimated_gas_price": estimated_gas_price, "estimated_total_gas_used": total_gas, "estimated_amount_required": estimated_amount, - "token_symbol": token_symbol, }) )?; } diff --git a/crates/test-utils/src/script.rs b/crates/test-utils/src/script.rs index 45dbbbebdd73a..07413fef5495c 100644 --- a/crates/test-utils/src/script.rs +++ b/crates/test-utils/src/script.rs @@ -121,9 +121,32 @@ impl ScriptTester { let to_dir = root.join("utils"); fs::create_dir_all(&to_dir)?; for entry in fs::read_dir(&from_dir)? { - let file = &entry?.path(); - let name = file.file_name().unwrap(); - fs::copy(file, to_dir.join(name))?; + let file = entry?.path(); + // Only operate on regular files to avoid following symlinks or directories + let metadata = fs::symlink_metadata(&file)?; + let ftype = metadata.file_type(); + if !ftype.is_file() { + continue; + } + let name = match file.file_name() { + Some(name) => name, + None => continue, + }; + // Validate file name to avoid path traversal and absolute paths + let name_str = name.to_string_lossy(); + if name_str.contains("..") || name_str.contains("/") || name_str.contains("\\") { + // Skip invalid (potentially dangerous) file names + continue; + } + // Verify canonicalized file is in from_dir to avoid symlink traversal + if let Ok(canonical_file) = file.canonicalize() { + if !canonical_file.starts_with(&from_dir) { + continue; + } + } else { + continue; + } + fs::copy(&file, to_dir.join(name))?; } Ok(()) } diff --git a/crates/verify/src/etherscan/standard_json.rs b/crates/verify/src/etherscan/standard_json.rs index 8a38485e48922..0471e3e42888e 100644 --- a/crates/verify/src/etherscan/standard_json.rs +++ b/crates/verify/src/etherscan/standard_json.rs @@ -56,7 +56,7 @@ impl EtherscanSourceProvider for EtherscanStandardJsonSource { let sources = Source::read_all_from(path, &["vy", "vyi"])?; let input = VyperInput::new( sources, - context.clone().compiler_settings.vyper, + context.compiler_settings.vyper.clone(), &context.compiler_version, ); diff --git a/flake.nix b/flake.nix index 5caaab9934aec..8cf41ed16d3a3 100644 --- a/flake.nix +++ b/flake.nix @@ -19,8 +19,7 @@ lib = pkgs.lib; toolchain = fenix.packages.${system}.stable.toolchain; - in - { + in { default = pkgs.mkShell { nativeBuildInputs = with pkgs; [ pkg-config @@ -29,16 +28,13 @@ # test dependencies solc vyper - dprint nodejs ]; + buildInputs = lib.optionals pkgs.stdenv.isDarwin + [ pkgs.darwin.apple_sdk.frameworks.AppKit ]; packages = with pkgs; [ rust-analyzer-unwrapped ]; - # Remove the hardening added by nix to fix jmalloc compilation error. - # More info: https://github.com/tikv/jemallocator/issues/108 - hardeningDisable = [ "fortify" ]; - # Environment variables RUST_SRC_PATH = "${toolchain}/lib/rustlib/src/rust/library"; LD_LIBRARY_PATH = lib.makeLibraryPath [ pkgs.libusb1 ]; diff --git a/npm/package.json b/npm/package.json index 2362816053f8c..d596a7930b609 100644 --- a/npm/package.json +++ b/npm/package.json @@ -8,7 +8,7 @@ }, "dependencies": { "@types/bun": "^1.3.1", - "@types/node": "^24.9.1", + "@types/node": "^25.0.2", "bun": "^1.3.1", "typescript": "^5.9.3" }, diff --git a/npm/scripts/stage-from-artifact.mjs b/npm/scripts/stage-from-artifact.mjs index c1ca22c8bb2ed..1d39fdc82e84f 100755 --- a/npm/scripts/stage-from-artifact.mjs +++ b/npm/scripts/stage-from-artifact.mjs @@ -64,10 +64,10 @@ function resolveArgs() { strict: true }) - const tool = requireValue(values.tool || process.env.TARGET_TOOL, 'tool') - const platform = requireValue(values.platform || process.env.PLATFORM_NAME, 'platform') - const arch = requireValue(values.arch || process.env.ARCH, 'arch') - const releaseVersion = requireValue( + const tool = requireSafeIdentifier(values.tool || process.env.TARGET_TOOL, 'tool') + const platform = requireSafeIdentifier(values.platform || process.env.PLATFORM_NAME, 'platform') + const arch = requireSafeIdentifier(values.arch || process.env.ARCH, 'arch') + const releaseVersion = requireSafeIdentifier( values.release || values['release-version'] || process.env.RELEASE_VERSION, 'release version' ) @@ -95,6 +95,26 @@ function requireValue(value, name) { throw new Error(`Missing required ${name}`) } +/** + * Ensure a required value is present and consists only of safe identifier + * characters suitable for use in file and directory names. + * + * Allowed characters: letters, digits, dot, underscore, and hyphen. + * + * @param {string | undefined} value + * @param {string} name + * @returns {string} + */ +function requireSafeIdentifier(value, name) { + const trimmed = requireValue(value, name) + if (!/^[A-Za-z0-9._-]+$/.test(trimmed)) { + throw new Error( + `Invalid ${name}: "${trimmed}". Only letters, digits, ".", "_", and "-" are allowed.` + ) + } + return trimmed +} + /** * Determine which archive variant exists for the given artifact prefix. * @param {string} prefix diff --git a/npm/src/const.mjs b/npm/src/const.mjs index 6b3dcf3f9fbed..e606759888acb 100644 --- a/npm/src/const.mjs +++ b/npm/src/const.mjs @@ -1,4 +1,5 @@ import * as NodePath from 'node:path' +import { URL } from 'node:url' /** * @typedef {'amd64' | 'arm64'} Arch @@ -33,11 +34,36 @@ export function resolveTargetTool(raw = process.env.TARGET_TOOL || process.argv[ export function getRegistryUrl() { // Prefer npm's configured registry (works with Verdaccio and custom registries) // Fallback to REGISTRY_URL for tests/dev, then npmjs - return ( + const raw = process.env.npm_config_registry || process.env.REGISTRY_URL || 'https://registry.npmjs.org' - ) + + let parsed + try { + parsed = new URL(raw) + } catch { + throw new Error(`Invalid registry URL: "${raw}"`) + } + + // Enforce secure scheme + if (parsed.protocol !== 'https:') { + throw new Error(`Insecure registry URL scheme "${parsed.protocol}". Only "https:" is allowed.`) + } + + // Basic SSRF mitigation: disallow obvious loopback hosts + const hostname = parsed.hostname.toLowerCase() + if ( + hostname === 'localhost' + || hostname === '127.0.0.1' + || hostname === '::1' + ) { + throw new Error(`Registry URL host "${parsed.hostname}" is not allowed.`) + } + + // Normalize to a consistent base URL without trailing slash + const base = parsed.origin + parsed.pathname + return base.replace(/\/+$/, '') } /** From eaf1abe653e58669070007dbd2a3a11f4c44c67e Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Wed, 28 Jan 2026 15:00:43 +0700 Subject: [PATCH 211/232] Potential fix for code scanning alert no. 102: Artifact poisoning (#354) * Potential fix for code scanning alert no. 102: Artifact poisoning Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> * Update .github/workflows/npm.yml Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> --------- Signed-off-by: Dargon789 <64915515+Dargon789@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> --- .github/workflows/npm.yml | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/.github/workflows/npm.yml b/.github/workflows/npm.yml index df45e41a50295..741590095fec5 100644 --- a/.github/workflows/npm.yml +++ b/.github/workflows/npm.yml @@ -136,6 +136,36 @@ jobs: github-token: ${{ secrets.GITHUB_TOKEN }} run-id: ${{ github.event.workflow_run.id || inputs.run_id }} + - name: Validate Downloaded Artifacts + env: + ARTIFACT_DIR: ${{ steps.paths.outputs.artifact_dir }} + run: | + set -euo pipefail + + echo "Validating artifacts in: $ARTIFACT_DIR" + + if [[ ! -d "$ARTIFACT_DIR" ]]; then + echo "ERROR: Artifact directory does not exist: $ARTIFACT_DIR" >&2 + exit 1 + fi + + if ! find "$ARTIFACT_DIR" -mindepth 1 -print -quit | grep -q .; then + echo "ERROR: Artifact directory is empty: $ARTIFACT_DIR" >&2 + exit 1 + fi + + # Reject files with suspicious paths (absolute paths or parent directory traversals) + # Use null-delimited paths to safely handle filenames with newlines or whitespace + while IFS= read -r -d '' path; do + rel="${path#"$ARTIFACT_DIR"/}" + if [[ "$rel" == /* ]] || [[ "$rel" == *".."* ]]; then + echo "ERROR: Suspicious artifact path detected: $rel" >&2 + exit 1 + fi + done < <(find "$ARTIFACT_DIR" -type f -print0) + + echo "Artifact validation completed successfully." + - name: Setup Bun uses: oven-sh/setup-bun@3d267786b128fe76c2f16a390aa2448b815359f3 # v2 with: From 3ff465c909d0ac9f933f3f5abe6e6491cbcafce9 Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Wed, 28 Jan 2026 16:32:33 +0700 Subject: [PATCH 212/232] fix(config): Respect user-configured etherscan URL over chain defaults (#13238) (#357) * fix(config): respect user-configured etherscan URL over chain defaults * test(config): add tests for custom etherscan URL handling Co-authored-by: Yuya Maruyama <69783679+YuyaMaruyama21D4E@users.noreply.github.com> --- crates/config/src/etherscan.rs | 63 ++++++++++++++++++++++++++++++---- 1 file changed, 57 insertions(+), 6 deletions(-) diff --git a/crates/config/src/etherscan.rs b/crates/config/src/etherscan.rs index 5999825e94681..e24f92b7d931e 100644 --- a/crates/config/src/etherscan.rs +++ b/crates/config/src/etherscan.rs @@ -319,10 +319,17 @@ impl ResolvedEtherscanConfig { .with_client(client) .with_api_key(api_key) .with_cache(cache, Duration::from_secs(24 * 60 * 60)); - if let Some(browser_url) = browser_url { + if let Some(ref browser_url) = browser_url { client_builder = client_builder.with_url(browser_url)?; } - client_builder.chain(chain)?.build() + + // Use the provided URL (either custom from foundry.toml or chain's default from resolve()) + client_builder = client_builder.with_api_url(api_url.clone())?; + // Fallback: Use api_url as browser URL if browser_url is not set + if browser_url.is_none() { + client_builder = client_builder.with_url(api_url)?; + } + client_builder.build() } } @@ -478,10 +485,8 @@ mod tests { let config = resolved.remove("mainnet").unwrap().unwrap(); assert_eq!(config.key, "ABCDEFG"); let client = config.into_client().unwrap(); - assert_eq!( - client.etherscan_api_url().as_str(), - "https://api.etherscan.io/v2/api?chainid=1" - ); + // Custom URL should be used even when chain has a default URL + assert_eq!(client.etherscan_api_url().as_str(), "https://api.etherscan.io/api"); unsafe { std::env::remove_var(env); @@ -518,4 +523,50 @@ mod tests { let resolved = config.resolve(Some("base-sepolia")).unwrap(); assert_eq!(resolved.chain, Some(Chain::base_sepolia())); } + + #[test] + fn can_create_client_with_custom_url_for_chain_without_default_url() { + // Chains without default Etherscan URLs (e.g., Dev, AnvilHardhat networks) + // should work if a custom URL is provided in foundry.toml. + let mut configs = EtherscanConfigs::default(); + configs.insert( + "dev".to_string(), + EtherscanConfig { + chain: Some(Chain::dev()), + url: Some("https://custom.api.url/verify/etherscan".to_string()), + key: EtherscanApiKey::Key("test_key".to_string()), + }, + ); + + let mut resolved = configs.resolved(); + let config = resolved.remove("dev").unwrap().unwrap(); + let result = config.into_client(); + assert!( + result.is_ok(), + "Should succeed with custom URL even for chains without default Etherscan URLs" + ); + } + + #[test] + fn fails_without_custom_url_for_chain_without_default_url() { + // Chains without default Etherscan URLs (e.g., Dev, AnvilHardhat networks) + // should fail if no custom URL is provided in foundry.toml. + let mut configs = EtherscanConfigs::default(); + configs.insert( + "dev".to_string(), + EtherscanConfig { + chain: Some(Chain::dev()), + url: None, + key: EtherscanApiKey::Key("test_key".to_string()), + }, + ); + + let mut resolved = configs.resolved(); + let config = resolved.remove("dev").unwrap(); + + assert!( + config.is_err(), + "Should fail: chains without default Etherscan URLs require custom URL" + ); + } } From a737f7f3a7a0ca7e92f06370e92f6155d7fcc2cc Mon Sep 17 00:00:00 2001 From: Dargon789 <64915515+Dargon789@users.noreply.github.com> Date: Thu, 5 Feb 2026 12:02:20 +0000 Subject: [PATCH 213/232] refactor(common): make ProviderBuilder generic over Network #13250 (#361) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor(common): make `ProviderBuilder` generic over `Network` (#13250) * refactor(common): make `ProviderBuilder` generic over `Network` - Updated `ProviderBuilder` helper to be generic, which will facilate `FoundryNetwork` rollout - Adjusted the instantiation of `ProviderBuilder` in various locations to use `AnyNetwork`. - Enhanced the `build` and `build_with_wallet` methods to accommodate the new generic structure. * fix: relax trait bound on `N::TransactionRequest` * fix: comment * fix: comment * fix(anvil): return error instead of empty vec for out-of-range log queries (#13251) * fix(config): respect user-configured etherscan URL over chain defaults (#13239) fix(config): Respect user-configured etherscan URL over chain defaults (#13238) * fix(config): respect user-configured etherscan URL over chain defaults * test(config): add tests for custom etherscan URL handling Co-authored-by: Yuya Maruyama <69783679+YuyaMaruyama21D4E@users.noreply.github.com> * fix(primitives): track both 4844/7594 sidecars presence in `FoundryTransactionRequest::build_typed_tx` (#13218) * fix(primitives): track both 4844/7594 sidecars presence in `FoundryTransactionRequest::build_typed_tx` * fix: after `TransactionBuilder4844` impl * feat(common): introduce generic `ProviderBuilder::from_config` method (#13268) - keep the existing helpers that erase generic to avoid breaking change * fix(cast): remove redundant chain() call in explorer_client (#13272) Co-authored-by: tefyosL-sol * fix(verify): respect user-configured etherscan URL over chain defaults (#13275) Co-authored-by: tefyosL-sol * Update flake.lock (#13279) flake.lock: Update Flake lock file updates: • Updated input 'fenix': 'github:nix-community/fenix/93523fa' (2026-01-24) → 'github:nix-community/fenix/b2344f3' (2026-01-31) • Updated input 'fenix/rust-analyzer-src': 'github:rust-lang/rust-analyzer/39018ac' (2026-01-23) → 'github:rust-lang/rust-analyzer/eb05888' (2026-01-30) • Updated input 'nixpkgs': 'github:NixOS/nixpkgs/ab9fbbc' (2026-01-24) → 'github:NixOS/nixpkgs/6308c3b' (2026-01-30) Co-authored-by: github-actions[bot] * fix(invariant): remove unused cloned calldata (#12893) * fix(invariant): prune calldata to bound memory usage in long runs * style: fix formatting in invariant executor * chore: remove vyper files from testdata to fix CI * chore: trigger ci update * fix(invariant): remove unused FuzzCase.calldata field to prevent OOM The calldata field in FuzzCase was stored but never read after construction. Removing it entirely eliminates memory accumulation during long invariant runs. Changes: - Remove FuzzCase.calldata field (unused after construction) - Remove prune_calldata() methods (no longer needed) - Restore vyper test files that were incorrectly deleted Fixes #12397 Amp-Thread-ID: https://ampcode.com/threads/T-019c17c9-d969-7370-bf0d-495e473e8e30 Co-authored-by: Amp Amp-Thread-ID: https://ampcode.com/threads/T-019c17c9-d969-7370-bf0d-495e473e8e30 Co-authored-by: Amp --------- Co-authored-by: Georgios Konstantopoulos Co-authored-by: Amp * feat(debugger): display actual gas usage alongside refund counter (#13271) * feat(debugger): display actual gas usage alongside refund counter * fix(forge-test): fix flamegraph gas inaccuracy issues * reverse `--decode-internal` not default with `--flamechart` * make gas unsigned as `inferno` doesn't support anyway * replace revm-inspectors patch * fix clippy * update tests * update tests * fmt * fix(config): handle decimal string in U256 deserialization (#13284) * fix: adjust numerical cells in gas report to be right aligned (#12883) * Adjust Cells to be Right Aligned in Gas Report * fix test and fmt --------- Co-authored-by: zerosnacks <95942363+zerosnacks@users.noreply.github.com> * chore(deps): weekly `cargo update` (#13280) Updating git repository `https://github.com/rust-cli/rexpect` Updating git repository `https://github.com/paradigmxyz/solar` Skipping git submodule `https://github.com/argotorg/solidity.git` due to update strategy in .gitmodules Updating git repository `https://github.com/tempoxyz/tempo` Updating git repository `https://github.com/paradigmxyz/reth` Locking 35 packages to latest compatible versions Updating alloy-dyn-abi v1.5.2 -> v1.5.4 Unchanged alloy-evm v0.26.3 (available: v0.27.0) Updating alloy-json-abi v1.5.2 -> v1.5.4 Unchanged alloy-op-evm v0.26.3 (available: v0.27.0) Updating alloy-primitives v1.5.2 -> v1.5.4 Updating alloy-sol-macro v1.5.2 -> v1.5.4 Updating alloy-sol-macro-expander v1.5.2 -> v1.5.4 Updating alloy-sol-macro-input v1.5.2 -> v1.5.4 Updating alloy-sol-type-parser v1.5.2 -> v1.5.4 Updating alloy-sol-types v1.5.2 -> v1.5.4 Updating annotate-snippets v0.12.10 -> v0.12.11 Updating aws-smithy-async v1.2.7 -> v1.2.10 Updating aws-smithy-http-client v1.1.5 -> v1.1.8 Updating aws-smithy-observability v0.2.0 -> v0.2.3 Updating aws-smithy-query v0.60.9 -> v0.60.12 Updating aws-smithy-runtime-api v1.10.0 -> v1.11.2 Updating aws-smithy-types v1.3.6 -> v1.4.2 Updating bytemuck v1.24.0 -> v1.25.0 Updating cc v1.2.54 -> v1.2.55 Updating clap v4.5.54 -> v4.5.56 Updating clap_builder v4.5.54 -> v4.5.56 Updating clap_derive v4.5.49 -> v4.5.55 Updating cliclack v0.3.7 -> v0.3.8 Updating find-msvc-tools v0.1.8 -> v0.1.9 Unchanged generic-array v0.14.7 (available: v0.14.9) Updating iana-time-zone v0.1.64 -> v0.1.65 Unchanged icu_collections v2.0.0 (available: v2.1.1) Unchanged icu_normalizer v2.0.1 (available: v2.1.1) Unchanged icu_normalizer_data v2.0.0 (available: v2.1.1) Unchanged icu_properties v2.0.2 (available: v2.1.2) Unchanged icu_properties_data v2.0.1 (available: v2.1.2) Unchanged idna_adapter v1.1.0 (available: v1.2.1) Updating keccak-asm v0.1.4 -> v0.1.5 Unchanged matchit v0.8.4 (available: v0.8.6) Updating notify-types v2.0.0 -> v2.1.0 Updating portable-atomic v1.13.0 -> v1.13.1 Updating portable-atomic-util v0.2.4 -> v0.2.5 Unchanged rand v0.8.5 (available: v0.9.2) Unchanged reqwest v0.12.28 (available: v0.13.1) Updating revm-inspectors v0.34.0 -> v0.34.2 Updating sha3-asm v0.1.4 -> v0.1.5 Updating siphasher v1.0.1 -> v1.0.2 Updating slab v0.4.11 -> v0.4.12 Updating syn-solidity v1.5.2 -> v1.5.4 Removing tiny-keccak v2.0.2 Updating zerocopy v0.8.33 -> v0.8.37 Updating zerocopy-derive v0.8.33 -> v0.8.37 Updating zmij v1.0.16 -> v1.0.18 note: to see how you depend on a package, run `cargo tree --invert @` Co-authored-by: mattsse <19890894+mattsse@users.noreply.github.com> Co-authored-by: DaniPopes <57450786+DaniPopes@users.noreply.github.com> * chore: update RPC URLs from ithaca.xyz to reth.rs (#13261) * chore: update RPC URLs from ithaca.xyz to reth.rs Co-authored-by: Tim Beiko Amp-Thread-ID: https://ampcode.com/threads/T-019c0a51-3f0a-76eb-ba4a-bfb6a697d9ba Co-authored-by: Amp * fix * fmt * Update rpc.rs * Update rpc.rs * test: update test --------- Co-authored-by: Tim Beiko Co-authored-by: Amp Co-authored-by: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Co-authored-by: zerosnacks <95942363+zerosnacks@users.noreply.github.com> Co-authored-by: Matthias Seitz Co-authored-by: Oliver Nordbjerg Co-authored-by: onbjerg * ci(bench): use depot runner for benchmarks (#13288) * feat(cli): cli markdown docs (#13291) * feat: add foundry-cli-markdown crate Add a new crate for generating Markdown documentation from clap CLIs. This is a fork of clap-markdown with the following enhancements: - Support for grouped options by help heading (PR #48) - Show environment variable names for arguments (PR #50) - Add version information to generated Markdown (PR #52) * feat(cli): add hidden --markdown-help flag Add a hidden --markdown-help flag to forge, cast, anvil, and chisel that prints CLI reference documentation as Markdown and exits. This uses the new foundry-cli-markdown crate to generate the output. * chore(deps): bump docker/login-action from 3.6.0 to 3.7.0 (#13298) Bumps [docker/login-action](https://github.com/docker/login-action) from 3.6.0 to 3.7.0. - [Release notes](https://github.com/docker/login-action/releases) - [Commits](https://github.com/docker/login-action/compare/5e57cd118135c172c3672efd75eb46360885c0ef...c94ce9fb468520275223c153574b00df6fe4bcc9) --- updated-dependencies: - dependency-name: docker/login-action dependency-version: 3.7.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump taiki-e/install-action from 2.67.13 to 2.67.18 (#13297) Bumps [taiki-e/install-action](https://github.com/taiki-e/install-action) from 2.67.13 to 2.67.18. - [Release notes](https://github.com/taiki-e/install-action/releases) - [Changelog](https://github.com/taiki-e/install-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/taiki-e/install-action/compare/710817a1645ef40daad5bcde7431ceccf6cc3528...650c5ca14212efbbf3e580844b04bdccf68dac31) --- updated-dependencies: - dependency-name: taiki-e/install-action dependency-version: 2.67.18 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump DeterminateSystems/update-flake-lock from 727cc5b0b19bc265bd5ef28fc66bccb284473b5d to 5adeaaaf36f64df54f62adb34aa5fbfdb0109d34 (#13299) chore(deps): bump DeterminateSystems/update-flake-lock Bumps [DeterminateSystems/update-flake-lock](https://github.com/determinatesystems/update-flake-lock) from 727cc5b0b19bc265bd5ef28fc66bccb284473b5d to 5adeaaaf36f64df54f62adb34aa5fbfdb0109d34. - [Release notes](https://github.com/determinatesystems/update-flake-lock/releases) - [Commits](https://github.com/determinatesystems/update-flake-lock/compare/727cc5b0b19bc265bd5ef28fc66bccb284473b5d...5adeaaaf36f64df54f62adb34aa5fbfdb0109d34) --- updated-dependencies: - dependency-name: DeterminateSystems/update-flake-lock dependency-version: 5adeaaaf36f64df54f62adb34aa5fbfdb0109d34 dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore(deps): bump mikepenz/release-changelog-builder-action from 6.0.1 to 6.1.0 (#13300) chore(deps): bump mikepenz/release-changelog-builder-action Bumps [mikepenz/release-changelog-builder-action](https://github.com/mikepenz/release-changelog-builder-action) from 6.0.1 to 6.1.0. - [Release notes](https://github.com/mikepenz/release-changelog-builder-action/releases) - [Commits](https://github.com/mikepenz/release-changelog-builder-action/compare/439f79b5b5428107c7688c1d2b0e8bacc9b8792c...6faf020194b7c8853f9e55c4fd92e40b02122a04) --- updated-dependencies: - dependency-name: mikepenz/release-changelog-builder-action dependency-version: 6.1.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * chore: fix typos CI (#13303) - Add consts to typos ignore list (valid Rust std::env::consts) - Fix LintCotext -> LintContext typos in linter docs * chore(deps): bump crate-ci/typos from 1.42.2 to 1.43.0 (#13296) Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.42.2 to 1.43.0. - [Release notes](https://github.com/crate-ci/typos/releases) - [Changelog](https://github.com/crate-ci/typos/blob/master/CHANGELOG.md) - [Commits](https://github.com/crate-ci/typos/compare/a1d64977b4aa1709d6328d518aa753f4899352d8...93cbdb2d23269548cf0db0f74d0bc6a09a3f0d5c) --- updated-dependencies: - dependency-name: crate-ci/typos dependency-version: 1.43.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * sec: bump to `bytes` `^1.11.1` for `RUSTSEC-2026-0007` (#13306) bump to 1.11.1 for patch: https://rustsec.org/advisories/RUSTSEC-2026-0007 * chore(anvil,cast): remove unnecessary `populate_blob_hashes()` (#13308) Both `set_blob_sidecar`/`set_blob_sidecar_7594` implement a call to `populate_blob_hashes()` * feat(forge): generate random fuzz seed if none provided (#13309) * feat(forge): generate random fuzz seed if none provided Generate a random seed for fuzz/invariant tests when no seed is explicitly configured. This ensures reproducibility by always having a seed available that can be passed via --fuzz-seed to reproduce test runs. * feat(forge): print fuzz seed on fuzz failure (#13310) * feat(forge): print fuzz seed on test failure When a fuzz or invariant test fails, print the seed used so users can reproduce the failure with --fuzz-seed. * test: update snapshots for fuzz seed output Add [SEED] redaction pattern to match 'Fuzz seed: 0x...' output. Update all test snapshots that have fuzz/invariant failures to include the new seed line. * fix: use [SEED] placeholder in issue_3055 test snapshot Amp-Thread-ID: https://ampcode.com/threads/T-019c26cb-9d21-74f9-9e49-7ea59885e827 Co-authored-by: Amp --------- Co-authored-by: Georgios Konstantopoulos Co-authored-by: Amp --------- Co-authored-by: Georgios Konstantopoulos Co-authored-by: Amp * feat(anvil): cache block timestamp in mined receipts (#13311) * fix: use shared `display_chain` helper in CLI error handler (#13314) * Update handler.rs * Update handler.rs * Add --enable-tx-gas-limit CLI flag for EIP-7825 support (#13307) add --enable-tx-gas-limit * fix(anvil): use consistent chain_id fallback in fork setup (#13276) Co-authored-by: tefyosL-sol * fix(test-utils): skip build artifacts when copying to temp workspace (#13266) * feat(lint): add common uppercase abbreviations to mixedCase exceptions (#13305) Co-authored-by: onbjerg * fix(fmt): correct indentation for closing brace in empty contracts with comments (#13319) Co-authored-by: onbjerg * feat(anvil): add `trace_replayBlockTransactions` endpoint for block txs tracing (#13098) Co-authored-by: onbjerg * fix(eip712): write diagnostics to stderr instead of stdout (#13293) Co-authored-by: onbjerg --------- Signed-off-by: dependabot[bot] Co-authored-by: Mablr <59505383+mablr@users.noreply.github.com> Co-authored-by: Matt D Co-authored-by: zerosnacks <95942363+zerosnacks@users.noreply.github.com> Co-authored-by: Yuya Maruyama <69783679+YuyaMaruyama21D4E@users.noreply.github.com> Co-authored-by: Theodore Solis Co-authored-by: tefyosL-sol Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] Co-authored-by: Yero~ Co-authored-by: Georgios Konstantopoulos Co-authored-by: Amp Co-authored-by: Philippe Dumonet Co-authored-by: Vicze Osikata Co-authored-by: Mahmoud Lababidi Co-authored-by: mattsse <19890894+mattsse@users.noreply.github.com> Co-authored-by: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Co-authored-by: Tim Beiko Co-authored-by: Matthias Seitz Co-authored-by: Oliver Nordbjerg Co-authored-by: onbjerg Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Alvarez <140459501+prestoalvarez@users.noreply.github.com> Co-authored-by: Ninja Co-authored-by: Himess <95512809+Himess@users.noreply.github.com> --- .github/workflows/benchmarks.yml | 2 +- .github/workflows/ci.yml | 4 +- .github/workflows/docker-publish.yml | 2 +- .github/workflows/nix.yml | 2 +- .github/workflows/release.yml | 2 +- .github/workflows/test-flaky.yml | 2 +- .github/workflows/test-isolate.yml | 2 +- .github/workflows/test.yml | 2 +- Cargo.lock | 188 +++--- Cargo.toml | 4 +- crates/anvil/core/src/eth/mod.rs | 10 +- crates/anvil/src/args.rs | 2 + crates/anvil/src/cmd.rs | 15 + crates/anvil/src/config.rs | 40 +- crates/anvil/src/eth/api.rs | 17 +- crates/anvil/src/eth/backend/fork.rs | 14 +- crates/anvil/src/eth/backend/mem/mod.rs | 118 +++- crates/anvil/src/eth/otterscan/api.rs | 10 +- crates/anvil/test-data/state-dump.json | 315 +++++++++- crates/anvil/tests/it/beacon_api.rs | 3 +- crates/anvil/tests/it/eip4844.rs | 47 +- crates/anvil/tests/it/state.rs | 1 + crates/anvil/tests/it/traces.rs | 80 ++- crates/cast/src/args.rs | 2 + crates/cast/src/lib.rs | 2 +- crates/cast/src/tx.rs | 2 - crates/cheatcodes/src/evm/fork.rs | 7 +- crates/chisel/src/args.rs | 2 + crates/cli-markdown/Cargo.toml | 20 + crates/cli-markdown/src/lib.rs | 582 ++++++++++++++++++ crates/cli/Cargo.toml | 1 + crates/cli/src/handler.rs | 4 +- crates/cli/src/opts/global.rs | 11 + crates/cli/src/utils/mod.rs | 27 +- crates/common/Cargo.toml | 1 + crates/common/src/provider/mod.rs | 86 ++- crates/config/src/lint.rs | 17 +- crates/config/src/utils.rs | 7 +- crates/debugger/src/node.rs | 7 +- crates/debugger/src/tui/draw.rs | 5 +- crates/evm/evm/src/executors/fuzz/mod.rs | 2 +- crates/evm/evm/src/executors/invariant/mod.rs | 8 +- crates/evm/fuzz/src/lib.rs | 2 - crates/evm/traces/src/folded_stack_trace.rs | 32 +- crates/fmt/src/state/sol.rs | 4 +- crates/fmt/testdata/CommentEmptyLine/fmt.sol | 5 + .../testdata/CommentEmptyLine/original.sol | 6 + crates/fmt/tests/formatter.rs | 26 + crates/forge/Cargo.toml | 1 + crates/forge/src/args.rs | 2 + crates/forge/src/cmd/eip712.rs | 2 +- crates/forge/src/cmd/test/mod.rs | 15 +- crates/forge/src/gas_report.rs | 26 +- crates/forge/src/result.rs | 35 +- crates/forge/tests/cli/cmd.rs | 152 ++--- crates/forge/tests/cli/script.rs | 4 +- crates/forge/tests/cli/test_cmd/fuzz.rs | 2 + .../tests/cli/test_cmd/invariant/common.rs | 28 + .../forge/tests/cli/test_cmd/invariant/mod.rs | 6 + .../tests/cli/test_cmd/invariant/target.rs | 8 + crates/forge/tests/cli/test_cmd/mod.rs | 4 + crates/forge/tests/cli/test_cmd/repros.rs | 2 + .../fixtures/SimpleContractTestVerbose.json | 5 + .../forge/tests/fixtures/invariant_traces.svg | 8 +- crates/lint/src/linter/early.rs | 2 +- crates/lint/src/linter/late.rs | 2 +- crates/lint/testdata/MixedCase.sol | 13 + crates/primitives/src/network/receipt.rs | 18 + crates/primitives/src/transaction/request.rs | 9 +- crates/test-utils/src/prj.rs | 14 +- crates/test-utils/src/rpc.rs | 10 +- crates/test-utils/src/util.rs | 48 +- crates/verify/src/etherscan/mod.rs | 17 +- flake.lock | 18 +- testdata/default/cheats/RpcUrls.t.sol | 2 +- typos.toml | 1 + 76 files changed, 1825 insertions(+), 379 deletions(-) create mode 100644 crates/cli-markdown/Cargo.toml create mode 100644 crates/cli-markdown/src/lib.rs create mode 100644 crates/fmt/testdata/CommentEmptyLine/fmt.sol create mode 100644 crates/fmt/testdata/CommentEmptyLine/original.sol diff --git a/.github/workflows/benchmarks.yml b/.github/workflows/benchmarks.yml index 34622ca7979a5..53e29ecd33691 100644 --- a/.github/workflows/benchmarks.yml +++ b/.github/workflows/benchmarks.yml @@ -29,7 +29,7 @@ env: jobs: run-benchmarks: name: Run All Benchmarks - runs-on: foundry-runner + runs-on: depot-ubuntu-24.04-32 permissions: contents: write steps: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f0ca528491f95..bdb7848f55f29 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -58,7 +58,7 @@ jobs: - uses: actions/checkout@v6 with: persist-credentials: false - - uses: crate-ci/typos@a1d64977b4aa1709d6328d518aa753f4899352d8 # v1 + - uses: crate-ci/typos@93cbdb2d23269548cf0db0f74d0bc6a09a3f0d5c # v1 shellcheck: runs-on: depot-ubuntu-latest @@ -140,7 +140,7 @@ jobs: with: toolchain: stable - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 - - uses: taiki-e/install-action@710817a1645ef40daad5bcde7431ceccf6cc3528 # v2 + - uses: taiki-e/install-action@650c5ca14212efbbf3e580844b04bdccf68dac31 # v2 with: tool: cargo-hack - uses: mozilla-actions/sccache-action@7d986dd989559c6ecdb630a3fd2557667be217ad # v0.0.9 diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 566844094730d..51e625d0d6d28 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -44,7 +44,7 @@ jobs: # Login against a Docker registry except on PR # https://github.com/docker/login-action - name: Login into registry ${{ env.REGISTRY }} - uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3 + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index 7c348a9726f90..8d39e71112494 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -23,7 +23,7 @@ jobs: - uses: actions/checkout@v6 with: persist-credentials: false - - uses: DeterminateSystems/update-flake-lock@727cc5b0b19bc265bd5ef28fc66bccb284473b5d # main + - uses: DeterminateSystems/update-flake-lock@5adeaaaf36f64df54f62adb34aa5fbfdb0109d34 # main with: pr-title: "Update flake.lock" pr-labels: | diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b18435be45d22..a267433f27ec2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -68,7 +68,7 @@ jobs: - name: Build changelog id: build_changelog - uses: mikepenz/release-changelog-builder-action@439f79b5b5428107c7688c1d2b0e8bacc9b8792c # v6 + uses: mikepenz/release-changelog-builder-action@6faf020194b7c8853f9e55c4fd92e40b02122a04 # v6 with: configuration: "./.github/changelog.json" fromTag: ${{ env.IS_NIGHTLY == 'true' && 'nightly' || env.STABLE_VERSION }} diff --git a/.github/workflows/test-flaky.yml b/.github/workflows/test-flaky.yml index 84029e775c2b4..858d1c8c43f2c 100644 --- a/.github/workflows/test-flaky.yml +++ b/.github/workflows/test-flaky.yml @@ -33,7 +33,7 @@ jobs: with: toolchain: stable - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 - - uses: taiki-e/install-action@710817a1645ef40daad5bcde7431ceccf6cc3528 # v2 + - uses: taiki-e/install-action@650c5ca14212efbbf3e580844b04bdccf68dac31 # v2 with: tool: nextest - uses: mozilla-actions/sccache-action@7d986dd989559c6ecdb630a3fd2557667be217ad # v0.0.9 diff --git a/.github/workflows/test-isolate.yml b/.github/workflows/test-isolate.yml index ee17ace188413..d24fbfca3d1a0 100644 --- a/.github/workflows/test-isolate.yml +++ b/.github/workflows/test-isolate.yml @@ -37,7 +37,7 @@ jobs: with: toolchain: stable - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 - - uses: taiki-e/install-action@710817a1645ef40daad5bcde7431ceccf6cc3528 # v2 + - uses: taiki-e/install-action@650c5ca14212efbbf3e580844b04bdccf68dac31 # v2 with: tool: nextest - uses: mozilla-actions/sccache-action@7d986dd989559c6ecdb630a3fd2557667be217ad # v0.0.9 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 25e32aac98b5e..abb8b8363eece 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -66,7 +66,7 @@ jobs: toolchain: stable target: ${{ matrix.target }} - uses: rui314/setup-mold@725a8794d15fc7563f59595bd9556495c0564878 # v1 - - uses: taiki-e/install-action@710817a1645ef40daad5bcde7431ceccf6cc3528 # v2 + - uses: taiki-e/install-action@650c5ca14212efbbf3e580844b04bdccf68dac31 # v2 with: tool: nextest diff --git a/Cargo.lock b/Cargo.lock index d9b1edda73916..7b638f17ed1a6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -143,9 +143,9 @@ dependencies = [ [[package]] name = "alloy-dyn-abi" -version = "1.5.2" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "369f5707b958927176265e8a58627fc6195e5dfa5c55689396e68b241b3a72e6" +checksum = "14ff5ee5f27aa305bda825c735f686ad71bb65508158f059f513895abe69b8c3" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -315,9 +315,9 @@ dependencies = [ [[package]] name = "alloy-json-abi" -version = "1.5.2" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84e3cf01219c966f95a460c95f1d4c30e12f6c18150c21a30b768af2a2a29142" +checksum = "8708475665cc00e081c085886e68eada2f64cfa08fc668213a9231655093d4de" dependencies = [ "alloy-primitives", "alloy-sol-type-parser", @@ -411,9 +411,9 @@ dependencies = [ [[package]] name = "alloy-primitives" -version = "1.5.2" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6a0fb18dd5fb43ec5f0f6a20be1ce0287c79825827de5744afaa6c957737c33" +checksum = "3b88cf92ed20685979ed1d8472422f0c6c2d010cec77caf63aaa7669cc1a7bc2" dependencies = [ "alloy-rlp", "arbitrary", @@ -437,7 +437,6 @@ dependencies = [ "rustc-hash", "serde", "sha3", - "tiny-keccak", ] [[package]] @@ -829,9 +828,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro" -version = "1.5.2" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09eb18ce0df92b4277291bbaa0ed70545d78b02948df756bbd3d6214bf39a218" +checksum = "f5fa1ca7e617c634d2bd9fa71f9ec8e47c07106e248b9fcbd3eaddc13cabd625" dependencies = [ "alloy-sol-macro-expander", "alloy-sol-macro-input", @@ -843,9 +842,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro-expander" -version = "1.5.2" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95d9fa2daf21f59aa546d549943f10b5cce1ae59986774019fbedae834ffe01b" +checksum = "27c00c0c3a75150a9dc7c8c679ca21853a137888b4e1c5569f92d7e2b15b5102" dependencies = [ "alloy-json-abi", "alloy-sol-macro-input", @@ -855,16 +854,16 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", + "sha3", "syn 2.0.114", "syn-solidity", - "tiny-keccak", ] [[package]] name = "alloy-sol-macro-input" -version = "1.5.2" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9396007fe69c26ee118a19f4dee1f5d1d6be186ea75b3881adf16d87f8444686" +checksum = "297db260eb4d67c105f68d6ba11b8874eec681caec5505eab8fbebee97f790bc" dependencies = [ "alloy-json-abi", "const-hex", @@ -880,9 +879,9 @@ dependencies = [ [[package]] name = "alloy-sol-type-parser" -version = "1.5.2" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af67a0b0dcebe14244fc92002cd8d96ecbf65db4639d479f5fcd5805755a4c27" +checksum = "94b91b13181d3bcd23680fd29d7bc861d1f33fbe90fdd0af67162434aeba902d" dependencies = [ "serde", "winnow", @@ -890,9 +889,9 @@ dependencies = [ [[package]] name = "alloy-sol-types" -version = "1.5.2" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09aeea64f09a7483bdcd4193634c7e5cf9fd7775ee767585270cd8ce2d69dc95" +checksum = "fc442cc2a75207b708d481314098a0f8b6f7b58e3148dd8d8cc7407b0d6f9385" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -1024,9 +1023,9 @@ dependencies = [ [[package]] name = "annotate-snippets" -version = "0.12.10" +version = "0.12.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15580ece6ea97cbf832d60ba19c021113469480852c6a2a6beb0db28f097bf1f" +checksum = "16e4850548ff4a25a77ce3bda7241874e17fb702ea551f0cc62a2dbe052f1272" dependencies = [ "anstyle", "memchr", @@ -1874,9 +1873,9 @@ dependencies = [ [[package]] name = "aws-smithy-async" -version = "1.2.7" +version = "1.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ee19095c7c4dda59f1697d028ce704c24b2d33c6718790c7f1d5a3015b4107c" +checksum = "e39f47abe8641e434de98e047e85ced629862e7ab719b6914a846796ceb289e2" dependencies = [ "futures-util", "pin-project-lite", @@ -1906,9 +1905,9 @@ dependencies = [ [[package]] name = "aws-smithy-http-client" -version = "1.1.5" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59e62db736db19c488966c8d787f52e6270be565727236fd5579eaa301e7bc4a" +checksum = "a395c914b1ff95db3cb7003ea4fd19432343af698a9b5028a7d35f8e712240a1" dependencies = [ "aws-smithy-async", "aws-smithy-runtime-api", @@ -1939,18 +1938,18 @@ dependencies = [ [[package]] name = "aws-smithy-observability" -version = "0.2.0" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef1fcbefc7ece1d70dcce29e490f269695dfca2d2bacdeaf9e5c3f799e4e6a42" +checksum = "7764bc1dfdb71157bc481528a649e617ed8c9c8aa93c0e8b01087133677cfc8e" dependencies = [ "aws-smithy-runtime-api", ] [[package]] name = "aws-smithy-query" -version = "0.60.9" +version = "0.60.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae5d689cf437eae90460e944a58b5668530d433b4ff85789e69d2f2a556e057d" +checksum = "786bbf4434ed3e3413c5a1741abf53a0372dd48124ddb2091e6bff1b1b2582b5" dependencies = [ "aws-smithy-types", "urlencoding", @@ -1982,9 +1981,9 @@ dependencies = [ [[package]] name = "aws-smithy-runtime-api" -version = "1.10.0" +version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efce7aaaf59ad53c5412f14fc19b2d5c6ab2c3ec688d272fd31f76ec12f44fb0" +checksum = "8b743e9aab0b8d50a9a40eebedf974fcfe3621032e07c6388d1c7821b155b7b0" dependencies = [ "aws-smithy-async", "aws-smithy-types", @@ -1999,9 +1998,9 @@ dependencies = [ [[package]] name = "aws-smithy-types" -version = "1.3.6" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65f172bcb02424eb94425db8aed1b6d583b5104d4d5ddddf22402c661a320048" +checksum = "0828575b70da70406b4cdb5d4afe0afe725f72245f04d34f02e0fb5ebd6fc872" dependencies = [ "base64-simd", "bytes", @@ -2478,9 +2477,9 @@ checksum = "7575182f7272186991736b70173b0ea045398f984bf5ebbb3804736ce1330c9d" [[package]] name = "bytemuck" -version = "1.24.0" +version = "1.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" +checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" dependencies = [ "bytemuck_derive", ] @@ -2504,9 +2503,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" dependencies = [ "serde", ] @@ -2641,9 +2640,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.54" +version = "1.2.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6354c81bbfd62d9cfa9cb3c773c2b7b2a3a482d569de977fd0e961f6e7c00583" +checksum = "47b26a0954ae34af09b50f0de26458fa95369a0d478d8236d3f93082b219bd29" dependencies = [ "find-msvc-tools", "jobserver", @@ -2757,9 +2756,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.54" +version = "4.5.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6e6ff9dcd79cff5cd969a17a545d79e84ab086e444102a591e288a8aa3ce394" +checksum = "a75ca66430e33a14957acc24c5077b503e7d374151b2b4b3a10c83b4ceb4be0e" dependencies = [ "clap_builder", "clap_derive", @@ -2777,9 +2776,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.54" +version = "4.5.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa42cf4d2b7a41bc8f663a7cab4031ebafa1bf3875705bfaf8466dc60ab52c00" +checksum = "793207c7fa6300a0608d1080b858e5fdbe713cdc1c8db9fb17777d8a13e63df0" dependencies = [ "anstream", "anstyle", @@ -2811,9 +2810,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.49" +version = "4.5.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" +checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5" dependencies = [ "heck", "proc-macro2", @@ -2842,9 +2841,9 @@ dependencies = [ [[package]] name = "cliclack" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2381872509dfa50d8b92b92a5da8367ba68458ab9494be4134b57ad6ca26295f" +checksum = "aa510b739c618c679375ea9c5af44ce9f591289546e874ad5910e7ce7df79844" dependencies = [ "console 0.15.11", "indicatif", @@ -3562,6 +3561,12 @@ dependencies = [ "zeroize", ] +[[package]] +name = "diff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + [[package]] name = "digest" version = "0.9.0" @@ -4107,9 +4112,9 @@ dependencies = [ [[package]] name = "find-msvc-tools" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8591b0bcc8a98a64310a2fae1bb3e9b8564dd10e381e6e28010fde8e8e8568db" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" [[package]] name = "fixed-hash" @@ -4222,6 +4227,7 @@ dependencies = [ "path-slash", "proptest", "quick-junit", + "rand 0.9.2", "rayon", "regex", "reqwest", @@ -4540,6 +4546,7 @@ dependencies = [ "dunce", "eyre", "foundry-block-explorers", + "foundry-cli-markdown", "foundry-common", "foundry-compilers", "foundry-config", @@ -4567,6 +4574,14 @@ dependencies = [ "yansi", ] +[[package]] +name = "foundry-cli-markdown" +version = "1.6.0" +dependencies = [ + "clap", + "pretty_assertions", +] + [[package]] name = "foundry-common" version = "1.6.0" @@ -4602,6 +4617,7 @@ dependencies = [ "foundry-block-explorers", "foundry-common-fmt", "foundry-compilers", + "foundry-config", "itertools 0.14.0", "jiff", "num-format", @@ -5728,9 +5744,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.64" +version = "0.1.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -6269,9 +6285,9 @@ dependencies = [ [[package]] name = "keccak-asm" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "505d1856a39b200489082f90d897c3f07c455563880bc5952e38eabf731c83b6" +checksum = "b646a74e746cd25045aa0fd42f4f7f78aa6d119380182c7e63a5593c4ab8df6f" dependencies = [ "digest 0.10.7", "sha3-asm", @@ -6875,9 +6891,12 @@ dependencies = [ [[package]] name = "notify-types" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e0826a989adedc2a244799e823aece04662b66609d96af8dff7ac6df9a8925d" +checksum = "42b8cfee0e339a0337359f3c88165702ac6e600dc01c0cc9579a92d62b08477a" +dependencies = [ + "bitflags 2.10.0", +] [[package]] name = "nu-ansi-term" @@ -7630,15 +7649,15 @@ checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] name = "portable-atomic" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f89776e4d69bb58bc6993e99ffa1d11f228b839984854c7daeb5d37f87cbe950" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" [[package]] name = "portable-atomic-util" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +checksum = "7a9db96d7fa8782dd8c15ce32ffe8680bbd1e978a43bf51a34d39483540495f5" dependencies = [ "portable-atomic", ] @@ -7699,6 +7718,16 @@ dependencies = [ "termtree", ] +[[package]] +name = "pretty_assertions" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d" +dependencies = [ + "diff", + "yansi", +] + [[package]] name = "prettydiff" version = "0.9.0" @@ -8605,9 +8634,9 @@ dependencies = [ [[package]] name = "revm-inspectors" -version = "0.34.0" +version = "0.34.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a1ce3f52a052d78cc251714d57bf05dc8bc75e269677de11805d3153300a2cd" +checksum = "6e435414e9de50a1b930da602067c76365fea2fea11e80ceb50783c94ddd127f" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", @@ -9423,9 +9452,9 @@ dependencies = [ [[package]] name = "sha3-asm" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28efc5e327c837aa837c59eae585fc250715ef939ac32881bcc11677cd02d46" +checksum = "b31139435f327c93c6038ed350ae4588e2c70a13d50599509fee6349967ba35a" dependencies = [ "cc", "cfg-if", @@ -9533,15 +9562,15 @@ dependencies = [ [[package]] name = "siphasher" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" +checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" [[package]] name = "slab" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "small_btree" @@ -9678,7 +9707,7 @@ name = "solar-interface" version = "0.1.8" source = "git+https://github.com/paradigmxyz/solar?rev=530f129#530f129b1b2d7138df973dd71d2fc1e592b593d7" dependencies = [ - "annotate-snippets 0.12.10", + "annotate-snippets 0.12.11", "anstream", "anstyle", "derive_more", @@ -10058,9 +10087,9 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "1.5.2" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f92d01b5de07eaf324f7fca61cc6bd3d82bbc1de5b6c963e6fe79e86f36580d" +checksum = "2379beea9476b89d0237078be761cf8e012d92d5ae4ae0c9a329f974838870fc" dependencies = [ "paste", "proc-macro2", @@ -10332,15 +10361,6 @@ dependencies = [ "time-core", ] -[[package]] -name = "tiny-keccak" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" -dependencies = [ - "crunchy", -] - [[package]] name = "tinystr" version = "0.8.2" @@ -11937,18 +11957,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.33" +version = "0.8.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "668f5168d10b9ee831de31933dc111a459c97ec93225beb307aed970d1372dfd" +checksum = "7456cf00f0685ad319c5b1693f291a650eaf345e941d082fc4e03df8a03996ac" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.33" +version = "0.8.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c7962b26b0a8685668b671ee4b54d007a67d4eaf05fda79ac0ecf41e32270f1" +checksum = "1328722bbf2115db7e19d69ebcc15e795719e2d66b60827c6a69a117365e37a0" dependencies = [ "proc-macro2", "quote", @@ -12063,9 +12083,9 @@ checksum = "40990edd51aae2c2b6907af74ffb635029d5788228222c4bb811e9351c0caad3" [[package]] name = "zmij" -version = "1.0.16" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfcd145825aace48cff44a8844de64bf75feec3080e0aa5cdbde72961ae51a65" +checksum = "1966f8ac2c1f76987d69a74d0e0f929241c10e78136434e3be70ff7f58f64214" [[package]] name = "zopfli" diff --git a/Cargo.toml b/Cargo.toml index 870d36bc0787d..06a320a24b358 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,7 @@ members = [ "crates/primitives/", "crates/script-sequence/", "crates/test-utils/", + "crates/cli-markdown/", ] resolver = "2" @@ -255,6 +256,7 @@ forge-script-sequence = { path = "crates/script-sequence" } foundry-cheatcodes = { path = "crates/cheatcodes" } foundry-cheatcodes-spec = { path = "crates/cheatcodes/spec" } foundry-cli = { path = "crates/cli" } +foundry-cli-markdown = { path = "crates/cli-markdown" } foundry-common = { path = "crates/common" } foundry-common-fmt = { path = "crates/common/fmt" } foundry-config = { path = "crates/config" } @@ -343,7 +345,7 @@ alloy-op-evm = "0.26.3" # revm revm = { version = "34.0.0", default-features = false } -revm-inspectors = { version = "0.34.0", features = ["serde"] } +revm-inspectors = { version = "0.34.2", features = ["serde"] } op-revm = { version = "15.0.0", default-features = false } ## cli diff --git a/crates/anvil/core/src/eth/mod.rs b/crates/anvil/core/src/eth/mod.rs index fb4b774f775f9..ee28f59e67c9b 100644 --- a/crates/anvil/core/src/eth/mod.rs +++ b/crates/anvil/core/src/eth/mod.rs @@ -1,5 +1,5 @@ use crate::{eth::subscription::SubscriptionId, types::ReorgOptions}; -use alloy_primitives::{Address, B64, B256, Bytes, TxHash, U256}; +use alloy_primitives::{Address, B64, B256, Bytes, TxHash, U256, map::HashSet}; use alloy_rpc_types::{ BlockId, BlockNumberOrTag as BlockNumber, BlockOverrides, Filter, Index, anvil::{Forking, MineOptions}, @@ -10,6 +10,7 @@ use alloy_rpc_types::{ trace::{ filter::TraceFilter, geth::{GethDebugTracingCallOptions, GethDebugTracingOptions}, + parity::TraceType, }, }; use alloy_serde::WithOtherFields; @@ -325,6 +326,13 @@ pub enum EthRequest { #[serde(rename = "trace_filter", with = "sequence")] TraceFilter(TraceFilter), + /// Trace transaction endpoint for parity's `trace_replayBlockTransactions` + #[serde(rename = "trace_replayBlockTransactions")] + TraceReplayBlockTransactions( + #[serde(deserialize_with = "lenient_block_number::lenient_block_number")] BlockNumber, + HashSet, + ), + // Custom endpoints, they're not extracted to a separate type out of serde convenience /// send transactions impersonating specific account and contract addresses. #[serde( diff --git a/crates/anvil/src/args.rs b/crates/anvil/src/args.rs index 806c8bc992155..4dee7f830fa15 100644 --- a/crates/anvil/src/args.rs +++ b/crates/anvil/src/args.rs @@ -7,6 +7,8 @@ use foundry_cli::utils; pub fn run() -> Result<()> { setup()?; + foundry_cli::opts::GlobalArgs::check_markdown_help::(); + let mut args = Anvil::parse(); args.global.init()?; args.node.evm.resolve_rpc_alias(); diff --git a/crates/anvil/src/cmd.rs b/crates/anvil/src/cmd.rs index 31759962111b1..017cc1ceff3c3 100644 --- a/crates/anvil/src/cmd.rs +++ b/crates/anvil/src/cmd.rs @@ -234,6 +234,7 @@ impl NodeArgs { Ok(NodeConfig::default() .with_gas_limit(self.evm.gas_limit) .disable_block_gas_limit(self.evm.disable_block_gas_limit) + .enable_tx_gas_limit(self.evm.enable_tx_gas_limit) .with_gas_price(self.evm.gas_price) .with_hardfork(hardfork) .with_blocktime(self.block_time) @@ -544,6 +545,10 @@ pub struct AnvilEvmArgs { )] pub disable_block_gas_limit: bool, + /// Enable the transaction gas limit check as imposed by EIP-7825 (Osaka hardfork). + #[arg(long, visible_alias = "tx-gas-limit", help_heading = "Environment config")] + pub enable_tx_gas_limit: bool, + /// EIP-170: Contract code size limit in bytes. Useful to increase this because of tests. To /// disable entirely, use `--disable-code-size-limit`. By default, it is 0x6000 (~25kb). #[arg(long, value_name = "CODE_SIZE", help_heading = "Environment config")] @@ -895,6 +900,16 @@ mod tests { assert!(args.is_err()); } + #[test] + fn can_parse_enable_tx_gas_limit() { + let args: NodeArgs = NodeArgs::parse_from(["anvil", "--enable-tx-gas-limit"]); + assert!(args.evm.enable_tx_gas_limit); + + // Also test the alias + let args: NodeArgs = NodeArgs::parse_from(["anvil", "--tx-gas-limit"]); + assert!(args.evm.enable_tx_gas_limit); + } + #[test] fn can_parse_disable_code_size_limit() { let args: NodeArgs = NodeArgs::parse_from(["anvil", "--disable-code-size-limit"]); diff --git a/crates/anvil/src/config.rs b/crates/anvil/src/config.rs index 648cdeed0256b..57e08dd54fc87 100644 --- a/crates/anvil/src/config.rs +++ b/crates/anvil/src/config.rs @@ -14,7 +14,6 @@ use crate::{ }, mem::{self, in_memory_db::MemDb}, }; -use alloy_chains::Chain; use alloy_consensus::BlockHeader; use alloy_eips::{eip1559::BaseFeeParams, eip7840::BlobParams}; use alloy_evm::EvmEnv; @@ -1300,6 +1299,23 @@ latest block number: {latest_block}" ..Default::default() }; + // Determine chain_id early so we can use it consistently + let chain_id = if let Some(chain_id) = self.chain_id { + chain_id + } else { + let chain_id = if let Some(fork_chain_id) = fork_chain_id { + fork_chain_id.to() + } else { + provider.get_chain_id().await.wrap_err("failed to fetch network chain ID")? + }; + + // need to update the dev signers and env with the chain id + self.set_chain_id(Some(chain_id)); + env.evm_env.cfg_env.chain_id = chain_id; + env.tx.base.chain_id = chain_id.into(); + chain_id + }; + // if not set explicitly we use the base fee of the latest block if self.base_fee.is_none() { if let Some(base_fee) = block.header.base_fee_per_gas { @@ -1320,12 +1336,7 @@ latest block number: {latest_block}" (block.header.excess_blob_gas, block.header.blob_gas_used) { // derive the blobparams that are active at this timestamp - let blob_params = get_blob_params( - fork_chain_id - .unwrap_or_else(|| U256::from(Chain::mainnet().id())) - .saturating_to(), - block.header.timestamp, - ); + let blob_params = get_blob_params(chain_id, block.header.timestamp); env.evm_env.block_env.blob_excess_gas_and_price = Some(BlobExcessGasAndPrice::new( blob_excess_gas, @@ -1353,21 +1364,6 @@ latest block number: {latest_block}" let block_hash = block.header.hash; - let chain_id = if let Some(chain_id) = self.chain_id { - chain_id - } else { - let chain_id = if let Some(fork_chain_id) = fork_chain_id { - fork_chain_id.to() - } else { - provider.get_chain_id().await.wrap_err("failed to fetch network chain ID")? - }; - - // need to update the dev signers and env with the chain id - self.set_chain_id(Some(chain_id)); - env.evm_env.cfg_env.chain_id = chain_id; - env.tx.base.chain_id = chain_id.into(); - chain_id - }; let override_chain_id = self.chain_id; // apply changes such as difficulty -> prevrandao and chain specifics for current chain id apply_chain_and_block_specific_env_changes::( diff --git a/crates/anvil/src/eth/api.rs b/crates/anvil/src/eth/api.rs index 7e623ea2bd986..a66f4f8d7d183 100644 --- a/crates/anvil/src/eth/api.rs +++ b/crates/anvil/src/eth/api.rs @@ -56,7 +56,7 @@ use alloy_rpc_types::{ trace::{ filter::TraceFilter, geth::{GethDebugTracingCallOptions, GethDebugTracingOptions, GethTrace}, - parity::LocalizedTransactionTrace, + parity::{LocalizedTransactionTrace, TraceResultsWithTransactionHash, TraceType}, }, txpool::{TxpoolContent, TxpoolInspect, TxpoolInspectSummary, TxpoolStatus}, }; @@ -344,6 +344,9 @@ impl EthApi { EthRequest::TraceTransaction(tx) => self.trace_transaction(tx).await.to_rpc_result(), EthRequest::TraceBlock(block) => self.trace_block(block).await.to_rpc_result(), EthRequest::TraceFilter(filter) => self.trace_filter(filter).await.to_rpc_result(), + EthRequest::TraceReplayBlockTransactions(block, trace_types) => { + self.trace_replay_block_transactions(block, trace_types).await.to_rpc_result() + } EthRequest::ImpersonateAccount(addr) => { self.anvil_impersonate_account(addr).await.to_rpc_result() } @@ -1990,6 +1993,18 @@ impl EthApi { node_info!("trace_filter"); self.backend.trace_filter(filter).await } + + /// Replays all transactions in a block returning the requested traces for each transaction + /// + /// Handler for RPC call: `trace_replayBlockTransactions` + pub async fn trace_replay_block_transactions( + &self, + block: BlockNumber, + trace_types: HashSet, + ) -> Result> { + node_info!("trace_replayBlockTransactions"); + self.backend.trace_replay_block_transactions(block, trace_types).await + } } // == impl EthApi anvil endpoints == diff --git a/crates/anvil/src/eth/backend/fork.rs b/crates/anvil/src/eth/backend/fork.rs index 995206fbfcc89..b7732446c8358 100644 --- a/crates/anvil/src/eth/backend/fork.rs +++ b/crates/anvil/src/eth/backend/fork.rs @@ -6,7 +6,7 @@ use alloy_eips::eip2930::AccessListResult; use alloy_network::{AnyRpcBlock, AnyRpcTransaction, BlockResponse, TransactionResponse}; use alloy_primitives::{ Address, B256, Bytes, StorageValue, U256, - map::{FbHashMap, HashMap}, + map::{FbHashMap, HashMap, HashSet}, }; use alloy_provider::{ Provider, @@ -19,7 +19,7 @@ use alloy_rpc_types::{ simulate::{SimulatePayload, SimulatedBlock}, trace::{ geth::{GethDebugTracingOptions, GethTrace}, - parity::LocalizedTransactionTrace as Trace, + parity::{LocalizedTransactionTrace as Trace, TraceResultsWithTransactionHash, TraceType}, }, }; use alloy_serde::WithOtherFields; @@ -419,6 +419,16 @@ impl ClientFork { Ok(traces) } + pub async fn trace_replay_block_transactions( + &self, + number: u64, + trace_types: HashSet, + ) -> Result, TransportError> { + // Forward to upstream provider for historical blocks + let params = (number, trace_types.iter().map(|t| format!("{t:?}")).collect::>()); + self.provider().raw_request("trace_replayBlockTransactions".into(), params).await + } + pub async fn transaction_receipt( &self, hash: B256, diff --git a/crates/anvil/src/eth/backend/mem/mod.rs b/crates/anvil/src/eth/backend/mem/mod.rs index 68de83c20bb13..78718fda4f72c 100644 --- a/crates/anvil/src/eth/backend/mem/mod.rs +++ b/crates/anvil/src/eth/backend/mem/mod.rs @@ -54,7 +54,7 @@ use alloy_network::{ }; use alloy_primitives::{ Address, B256, Bytes, TxHash, TxKind, U64, U256, hex, keccak256, logs_bloom, - map::{AddressMap, HashMap}, + map::{AddressMap, HashMap, HashSet}, }; use alloy_rpc_types::{ AccessList, Block as AlloyBlock, BlockId, BlockNumberOrTag as BlockNumber, BlockTransactions, @@ -71,7 +71,7 @@ use alloy_rpc_types::{ FourByteFrame, GethDebugBuiltInTracerType, GethDebugTracerType, GethDebugTracingCallOptions, GethDebugTracingOptions, GethTrace, NoopFrame, }, - parity::LocalizedTransactionTrace, + parity::{LocalizedTransactionTrace, TraceResultsWithTransactionHash, TraceType}, }, }; use alloy_serde::{OtherFields, WithOtherFields}; @@ -2141,8 +2141,7 @@ impl Backend { let from_block = self.convert_block_number(filter.block_option.get_from_block().copied()); if from_block > best { - // requested log range does not exist yet - return Ok(vec![]); + return Err(BlockchainError::BlockOutOfRange(best, from_block)); } self.logs_for_range(&filter, from_block, to_block).await @@ -2944,6 +2943,114 @@ impl Backend { Ok(vec![]) } + /// Replays all transactions in a block and returns the requested traces for each transaction + pub async fn trace_replay_block_transactions( + &self, + block: BlockNumber, + trace_types: HashSet, + ) -> Result, BlockchainError> { + let block_number = self.convert_block_number(Some(block)); + + // Try mined blocks first + if let Some(results) = + self.mined_parity_trace_replay_block_transactions(block_number, &trace_types) + { + return Ok(results); + } + + // Fallback to fork if block predates fork + if let Some(fork) = self.get_fork() + && fork.predates_fork(block_number) + { + return Ok(fork.trace_replay_block_transactions(block_number, trace_types).await?); + } + + Ok(vec![]) + } + + /// Returns the trace results for all transactions in a mined block by replaying them + fn mined_parity_trace_replay_block_transactions( + &self, + block_number: u64, + trace_types: &HashSet, + ) -> Option> { + let block = self.get_block(block_number)?; + + // Execute this in the context of the parent state + let parent_hash = block.header.parent_hash; + let trace_config = TracingInspectorConfig::from_parity_config(trace_types); + + let read_guard = self.states.upgradable_read(); + if let Some(state) = read_guard.get_state(&parent_hash) { + self.replay_block_transactions_with_inspector(&block, state, trace_config, trace_types) + } else { + let mut write_guard = RwLockUpgradableReadGuard::upgrade(read_guard); + let state = write_guard.get_on_disk_state(&parent_hash)?; + self.replay_block_transactions_with_inspector(&block, state, trace_config, trace_types) + } + } + + /// Replays all transactions in a block with the tracing inspector to generate TraceResults + fn replay_block_transactions_with_inspector( + &self, + block: &Block, + parent_state: &StateDb, + trace_config: TracingInspectorConfig, + trace_types: &HashSet, + ) -> Option> { + let mut cache_db = CacheDB::new(Box::new(parent_state)); + let mut results = Vec::new(); + + // Configure the block environment + let mut env = self.env.read().clone(); + env.evm_env.block_env = BlockEnv { + number: U256::from(block.header.number), + beneficiary: block.header.beneficiary, + timestamp: U256::from(block.header.timestamp), + difficulty: block.header.difficulty, + prevrandao: Some(block.header.mix_hash), + basefee: block.header.base_fee_per_gas.unwrap_or_default(), + gas_limit: block.header.gas_limit, + ..Default::default() + }; + + // Execute each transaction in the block with tracing + for tx_envelope in &block.body.transactions { + let tx_hash = tx_envelope.hash(); + + // Create a fresh inspector for this transaction + let mut inspector = TracingInspector::new(trace_config); + + // Prepare transaction environment + let pending_tx = + PendingTransaction::from_maybe_impersonated(tx_envelope.clone()).ok()?; + let mut tx_env: OpTransaction = FromRecoveredTx::from_recovered_tx( + pending_tx.transaction.as_ref(), + *pending_tx.sender(), + ); + if env.networks.is_optimism() { + tx_env.enveloped_tx = Some(pending_tx.transaction.encoded_2718().into()); + } + + // Execute the transaction with the inspector + let mut evm = self.new_evm_with_inspector_ref(&cache_db, &env, &mut inspector); + let result = evm.transact(tx_env.clone()).ok()?; + + // Build TraceResults from the inspector and execution result + let full_trace = inspector + .into_parity_builder() + .into_trace_results_with_state(&result, trace_types, &cache_db) + .ok()?; + + results.push(TraceResultsWithTransactionHash { transaction_hash: tx_hash, full_trace }); + + // Commit the state changes for the next transaction + cache_db.commit(result.state); + } + + Some(results) + } + pub async fn transaction_receipt( &self, hash: B256, @@ -3083,7 +3190,8 @@ impl Backend { blob_gas_used, }; - let inner = FoundryTxReceipt::new(receipt); + // Include timestamp in receipt to avoid extra block lookups (e.g., in Otterscan API) + let inner = FoundryTxReceipt::with_timestamp(receipt, block.header.timestamp); Some(MinedTransactionReceipt { inner, out: info.out }) } diff --git a/crates/anvil/src/eth/otterscan/api.rs b/crates/anvil/src/eth/otterscan/api.rs index 2e6fed286eb0f..3f4be8158f457 100644 --- a/crates/anvil/src/eth/otterscan/api.rs +++ b/crates/anvil/src/eth/otterscan/api.rs @@ -419,8 +419,14 @@ impl EthApi { let receipts = join_all(receipt_futs.map(|r| async { if let Ok(Some(r)) = r.await { - let block = self.block_by_number(r.block_number().unwrap().into()).await?; - let timestamp = block.ok_or(BlockchainError::BlockNotFound)?.header.timestamp; + // Try to get timestamp from receipt's other fields first (set by mined receipts), + // fallback to block lookup for fork receipts that may not have it + let timestamp = if let Some(ts) = r.block_timestamp() { + ts + } else { + let block = self.block_by_number(r.block_number().unwrap().into()).await?; + block.ok_or(BlockchainError::BlockNotFound)?.header.timestamp + }; let receipt = r.as_ref().inner.clone().map_inner(OtsReceipt::from); Ok(OtsTransactionReceipt { receipt, timestamp: Some(timestamp) }) } else { diff --git a/crates/anvil/test-data/state-dump.json b/crates/anvil/test-data/state-dump.json index a60e3c861c107..e7a1e37f62809 100644 --- a/crates/anvil/test-data/state-dump.json +++ b/crates/anvil/test-data/state-dump.json @@ -1 +1,314 @@ -{"block":{"number":2,"beneficiary":"0x0000000000000000000000000000000000000000","timestamp":1724763179,"gas_limit":30000000,"basefee":875175000,"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":2,"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":{"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","type":"0x2"},"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":{"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","type":"0x2"},"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": 2, + "beneficiary": "0x0000000000000000000000000000000000000000", + "timestamp": 1724763179, + "gas_limit": 30000000, + "basefee": 875175000, + "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": 2, + "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": { + "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", + "type": "0x2" + }, + "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": { + "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", + "type": "0x2" + }, + "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 + }, + "gas_refund_counter": 0 + }, + "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 + }, + "gas_refund_counter": 0 + }, + "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 + } + ] +} diff --git a/crates/anvil/tests/it/beacon_api.rs b/crates/anvil/tests/it/beacon_api.rs index 5c6c9b2486fa8..ec0f13c02e7c0 100644 --- a/crates/anvil/tests/it/beacon_api.rs +++ b/crates/anvil/tests/it/beacon_api.rs @@ -66,8 +66,7 @@ async fn test_beacon_api_get_blobs() { .with_blob_sidecar(sidecar) .value(U256::from(100)); - let mut tx = WithOtherFields::new(tx); - tx.populate_blob_hashes(); + let tx = WithOtherFields::new(tx); let pending = provider.send_transaction(tx).await.unwrap(); pending_txs.push(pending); diff --git a/crates/anvil/tests/it/eip4844.rs b/crates/anvil/tests/it/eip4844.rs index 11200e5667206..ddc8c91eefda7 100644 --- a/crates/anvil/tests/it/eip4844.rs +++ b/crates/anvil/tests/it/eip4844.rs @@ -39,9 +39,7 @@ async fn can_send_eip4844_transaction() { .with_blob_sidecar(sidecar) .value(U256::from(5)); - let mut tx = WithOtherFields::new(tx); - - tx.populate_blob_hashes(); + let tx = WithOtherFields::new(tx); let receipt = provider.send_transaction(tx).await.unwrap().get_receipt().await.unwrap(); @@ -103,6 +101,29 @@ async fn can_send_eip4844_transaction_eth_send_transaction() { let _blobs = api.anvil_get_blob_by_tx_hash(tx_hash).unwrap().unwrap(); } +// +#[tokio::test(flavor = "multi_thread")] +async fn can_send_eip4844_transaction_with_eip7594_sidecar_format() { + let node_config = NodeConfig::test().with_hardfork(Some(EthereumHardfork::Osaka.into())); + let (api, handle) = spawn(node_config).await; + let provider = ProviderBuilder::new().connect(handle.http_endpoint().as_str()).await.unwrap(); + let accounts = provider.get_accounts().await.unwrap(); + let alice = accounts[0]; + let bob = accounts[1]; + + let sidecar: SidecarBuilder = SidecarBuilder::from_slice(b"Blobs are fun!"); + let sidecar = sidecar.build_7594().unwrap(); + + let mut tx = TransactionRequest::default().with_from(alice).with_to(bob); + alloy_network::TransactionBuilder7594::set_blob_sidecar_7594(&mut tx, sidecar); + + let pending_tx = provider.send_transaction(tx).await.unwrap(); + let receipt = pending_tx.get_receipt().await.unwrap(); + let tx_hash = receipt.transaction_hash; + + let _blobs = api.anvil_get_blob_by_tx_hash(tx_hash).unwrap().unwrap(); +} + #[tokio::test(flavor = "multi_thread")] async fn can_send_multiple_blobs_in_one_tx() { let node_config = NodeConfig::test().with_hardfork(Some(EthereumHardfork::Cancun.into())); @@ -131,9 +152,7 @@ async fn can_send_multiple_blobs_in_one_tx() { .with_max_fee_per_gas(eip1559_est.max_fee_per_gas) .with_max_priority_fee_per_gas(eip1559_est.max_priority_fee_per_gas) .with_blob_sidecar(sidecar); - let mut tx = WithOtherFields::new(tx); - - tx.populate_blob_hashes(); + let tx = WithOtherFields::new(tx); let receipt = provider.send_transaction(tx).await.unwrap().get_receipt().await.unwrap(); @@ -169,9 +188,7 @@ async fn cannot_exceed_six_blobs() { .with_max_fee_per_gas(eip1559_est.max_fee_per_gas) .with_max_priority_fee_per_gas(eip1559_est.max_priority_fee_per_gas) .with_blob_sidecar(sidecar); - let mut tx = WithOtherFields::new(tx); - - tx.populate_blob_hashes(); + let tx = WithOtherFields::new(tx); let err = provider.send_transaction(tx).await.unwrap_err(); @@ -211,8 +228,6 @@ async fn can_mine_blobs_when_exceeds_max_blobs() { .with_blob_sidecar(sidecar); let mut tx = WithOtherFields::new(tx); - tx.populate_blob_hashes(); - let first_tx = provider.send_transaction(tx.clone()).await.unwrap(); let second_batch = vec![1u8; DATA_GAS_PER_BLOB as usize * 2]; @@ -224,7 +239,6 @@ async fn can_mine_blobs_when_exceeds_max_blobs() { let sidecar = sidecar.build().unwrap(); tx.set_blob_sidecar(sidecar); tx.set_nonce(1); - tx.populate_blob_hashes(); let second_tx = provider.send_transaction(tx).await.unwrap(); api.mine_one().await; @@ -428,9 +442,7 @@ async fn can_get_blobs_by_versioned_hash() { .with_blob_sidecar(sidecar.clone()) .value(U256::from(5)); - let mut tx = WithOtherFields::new(tx); - - tx.populate_blob_hashes(); + let tx = WithOtherFields::new(tx); let _receipt = provider.send_transaction(tx).await.unwrap().get_receipt().await.unwrap(); @@ -466,10 +478,7 @@ async fn can_get_blobs_by_tx_hash() { .with_blob_sidecar(sidecar.clone()) .value(U256::from(5)); - let mut tx = WithOtherFields::new(tx); - - tx.populate_blob_hashes(); - + let tx = WithOtherFields::new(tx); let receipt = provider.send_transaction(tx).await.unwrap().get_receipt().await.unwrap(); let hash = receipt.transaction_hash; api.anvil_set_auto_mine(true).await.unwrap(); diff --git a/crates/anvil/tests/it/state.rs b/crates/anvil/tests/it/state.rs index 9d35644f24949..2c677231e07ad 100644 --- a/crates/anvil/tests/it/state.rs +++ b/crates/anvil/tests/it/state.rs @@ -725,6 +725,7 @@ async fn test_backward_compatibility_state_dump_deserialization_v1_2() { "output": "0x608060405234801561000f575f5ffd5b506004361061003f575f3560e01c80633fb5c1cb146100435780638381f58a1461005f578063d09de08a1461007d575b5f5ffd5b61005d600480360381019061005891906100e4565b610087565b005b610067610090565b604051610074919061011e565b60405180910390f35b610085610095565b005b805f8190555050565b5f5481565b5f5f8154809291906100a690610164565b9190505550565b5f5ffd5b5f819050919050565b6100c3816100b1565b81146100cd575f5ffd5b50565b5f813590506100de816100ba565b92915050565b5f602082840312156100f9576100f86100ad565b5b5f610106848285016100d0565b91505092915050565b610118816100b1565b82525050565b5f6020820190506101315f83018461010f565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61016e826100b1565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036101a05761019f610137565b5b60018201905091905056fea264697066735822122040b6a3cd3ec8f890002f39a8719ebee029ba9bac3d7fa9d581d4712cfe9ffec264736f6c634300081e0033", "gas_used": 96345, "gas_limit": 143385, + "gas_refund_counter": 0, "status": "Return", "steps": [], "decoded": null diff --git a/crates/anvil/tests/it/traces.rs b/crates/anvil/tests/it/traces.rs index ba6c7ba887246..fb1777aa4f9f0 100644 --- a/crates/anvil/tests/it/traces.rs +++ b/crates/anvil/tests/it/traces.rs @@ -25,7 +25,7 @@ use alloy_rpc_types::{ GethDebugTracingCallOptions, GethDebugTracingOptions, GethTrace, PreStateConfig, PreStateFrame, }, - parity::{Action, LocalizedTransactionTrace}, + parity::{Action, ChangedType, LocalizedTransactionTrace, TraceType}, }, }; use alloy_serde::WithOtherFields; @@ -1273,3 +1273,81 @@ async fn test_debug_trace_transaction_pre_state_tracer() { _ => unreachable!(), } } + +#[tokio::test(flavor = "multi_thread")] +async fn test_trace_replay_block_transactions_local() { + let (api, handle) = spawn(NodeConfig::test()).await; + let provider = handle.http_provider(); + + api.anvil_set_auto_mine(false).await.unwrap(); + + let accounts = handle.dev_wallets().collect::>(); + let from = accounts[0].address(); + let to = accounts[1].address(); + let amount = U256::from(1000000u64); + + // Send first transaction + let tx1 = TransactionRequest::default().to(to).value(amount).from(from); + let tx1 = WithOtherFields::new(tx1); + let pending_tx1 = provider.send_transaction(tx1).await.unwrap(); + + // Send second transaction with different value + let tx2 = TransactionRequest::default().to(to).value(amount).from(from); + let tx2 = WithOtherFields::new(tx2); + let pending_tx2 = provider.send_transaction(tx2).await.unwrap(); + + api.mine_one().await; + let receipt1 = pending_tx1.get_receipt().await.unwrap(); + let receipt2 = pending_tx2.get_receipt().await.unwrap(); + + let block_number = receipt2.block_number.unwrap(); + + // Replay the block transactions with call trace type + // Pass block number as hex string as per Ethereum RPC spec + let results = api + .trace_replay_block_transactions( + block_number.into(), + vec![TraceType::Trace, TraceType::VmTrace, TraceType::StateDiff].into_iter().collect(), + ) + .await + .unwrap(); + + // Verify we have traces for both transactions + assert_eq!(results.len(), 2, "Should have traces for 2 transactions"); + + // Verify first transaction hash matches + assert_eq!(results[0].transaction_hash, receipt1.transaction_hash); + + // Verify second transaction hash matches + assert_eq!(results[1].transaction_hash, receipt2.transaction_hash); + + // Verify trace types are present and accurate + for result in results { + let full_trace = &result.full_trace; + + // Verify Trace (call trace) is present and accurate + assert!(!full_trace.trace.is_empty(), "Trace should not be empty"); + let first_trace = &full_trace.trace[0]; + match &first_trace.action { + Action::Call(call) => { + assert_eq!(call.from, from, "Call from address should match"); + assert_eq!(call.to, to, "Call to address should match"); + } + _ => panic!("Expected Call action, got {:?}", first_trace.action), + } + + // Verify VmTrace is present + assert!(full_trace.vm_trace.is_some(), "VmTrace should be present when requested"); + + // Verify StateDiff is present + assert!(full_trace.state_diff.is_some(), "StateDiff should be present when requested"); + // Verify balance change is correct in state diff + let ChangedType:: { from, to } = + full_trace.state_diff.as_ref().unwrap().get(&to).unwrap().balance.as_changed().unwrap(); + assert_eq!( + to.checked_sub(*from).unwrap(), + amount, + "Incorrect balance change in state diff" + ); + } +} diff --git a/crates/cast/src/args.rs b/crates/cast/src/args.rs index cf4966a86c15b..2f30b89e07216 100644 --- a/crates/cast/src/args.rs +++ b/crates/cast/src/args.rs @@ -33,6 +33,8 @@ use std::time::Instant; pub fn run() -> Result<()> { setup()?; + foundry_cli::opts::GlobalArgs::check_markdown_help::(); + let args = CastArgs::parse(); args.global.init()?; args.global.tokio_runtime().block_on(run_command(args)) diff --git a/crates/cast/src/lib.rs b/crates/cast/src/lib.rs index cf6c585bd1bdd..b24af1db60e84 100644 --- a/crates/cast/src/lib.rs +++ b/crates/cast/src/lib.rs @@ -2336,7 +2336,7 @@ fn explorer_client( api_url: Option, explorer_url: Option, ) -> Result { - let mut builder = Client::builder().chain(chain)?; + let mut builder = Client::builder(); let deduced = chain.etherscan_urls(); diff --git a/crates/cast/src/tx.rs b/crates/cast/src/tx.rs index 64ff8da391200..d38d27fec63dc 100644 --- a/crates/cast/src/tx.rs +++ b/crates/cast/src/tx.rs @@ -682,8 +682,6 @@ where self.tx.set_blob_sidecar_7594(sidecar); } - self.tx.populate_blob_hashes(); - Ok(self) } } diff --git a/crates/cheatcodes/src/evm/fork.rs b/crates/cheatcodes/src/evm/fork.rs index ea3a003a7ffc4..d32712219000e 100644 --- a/crates/cheatcodes/src/evm/fork.rs +++ b/crates/cheatcodes/src/evm/fork.rs @@ -3,6 +3,7 @@ use crate::{ json::json_value_to_token, }; use alloy_dyn_abi::DynSolValue; +use alloy_network::AnyNetwork; use alloy_primitives::{B256, U256}; use alloy_provider::Provider; use alloy_rpc_types::Filter; @@ -238,7 +239,7 @@ impl Cheatcode for eth_getLogsCall { .database .active_fork_url() .ok_or_else(|| fmt_err!("no active fork URL found"))?; - let provider = ProviderBuilder::new(&url).build()?; + let provider = ProviderBuilder::::new(&url).build()?; let mut filter = Filter::new().address(*target).from_block(from_block).to_block(to_block); for (i, &topic) in topics.iter().enumerate() { filter.topics[i] = topic.into(); @@ -275,7 +276,7 @@ impl Cheatcode for getRawBlockHeaderCall { .database .active_fork_url() .ok_or_else(|| fmt_err!("no active fork"))?; - let provider = ProviderBuilder::new(&url).build()?; + let provider = ProviderBuilder::::new(&url).build()?; let block_number = u64::try_from(blockNumber) .map_err(|_| fmt_err!("block number must be less than 2^64"))?; let block = @@ -397,7 +398,7 @@ fn persist_caller(ccx: &mut CheatsCtxt) { /// Performs an Ethereum JSON-RPC request to the given endpoint. fn rpc_call(url: &str, method: &str, params: &str) -> Result { - let provider = ProviderBuilder::new(url).build()?; + let provider = ProviderBuilder::::new(url).build()?; let params_json: serde_json::Value = serde_json::from_str(params)?; let result = foundry_common::block_on(provider.raw_request(method.to_string().into(), params_json)) diff --git a/crates/chisel/src/args.rs b/crates/chisel/src/args.rs index e3af6d5c91203..8200f4fc44f63 100644 --- a/crates/chisel/src/args.rs +++ b/crates/chisel/src/args.rs @@ -14,6 +14,8 @@ use yansi::Paint; pub fn run() -> Result<()> { setup()?; + foundry_cli::opts::GlobalArgs::check_markdown_help::(); + let args = Chisel::parse(); args.global.init()?; args.global.tokio_runtime().block_on(run_command(args)) diff --git a/crates/cli-markdown/Cargo.toml b/crates/cli-markdown/Cargo.toml new file mode 100644 index 0000000000000..7f039685d2cf1 --- /dev/null +++ b/crates/cli-markdown/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "foundry-cli-markdown" +description = "Generate Markdown documentation for clap CLIs" +version.workspace = true +edition.workspace = true +rust-version.workspace = true +authors.workspace = true +license.workspace = true +homepage.workspace = true +repository.workspace = true + +[lints] +workspace = true + +[dependencies] +clap = { version = "4", features = ["env"] } + +[dev-dependencies] +clap = { version = "4", features = ["derive"] } +pretty_assertions = "1" diff --git a/crates/cli-markdown/src/lib.rs b/crates/cli-markdown/src/lib.rs new file mode 100644 index 0000000000000..732e22bfd193d --- /dev/null +++ b/crates/cli-markdown/src/lib.rs @@ -0,0 +1,582 @@ +//! Generate Markdown documentation for clap command-line tools. +//! +//! This is a fork of [`clap-markdown`](https://crates.io/crates/clap-markdown) with the following +//! enhancements: +//! - Support for grouped options by help heading ([PR #48](https://github.com/ConnorGray/clap-markdown/pull/48)) +//! - Show environment variable names for arguments ([PR #50](https://github.com/ConnorGray/clap-markdown/pull/50)) +//! - Add version information to generated Markdown ([PR #52](https://github.com/ConnorGray/clap-markdown/pull/52)) + +use std::{ + collections::BTreeMap, + fmt::{self, Write}, +}; + +use clap::builder::PossibleValue; + +/// Options to customize the structure of the output Markdown document. +#[non_exhaustive] +pub struct MarkdownOptions { + title: Option, + show_footer: bool, + show_table_of_contents: bool, + show_aliases: bool, +} + +impl MarkdownOptions { + /// Construct a default instance of `MarkdownOptions`. + pub fn new() -> Self { + Self { title: None, show_footer: true, show_table_of_contents: true, show_aliases: true } + } + + /// Set a custom title to use in the generated document. + pub fn title(mut self, title: String) -> Self { + self.title = Some(title); + self + } + + /// Whether to show the default footer advertising `clap-markdown`. + pub fn show_footer(mut self, show: bool) -> Self { + self.show_footer = show; + self + } + + /// Whether to show the default table of contents. + pub fn show_table_of_contents(mut self, show: bool) -> Self { + self.show_table_of_contents = show; + self + } + + /// Whether to show aliases for arguments and commands. + pub fn show_aliases(mut self, show: bool) -> Self { + self.show_aliases = show; + self + } +} + +impl Default for MarkdownOptions { + fn default() -> Self { + Self::new() + } +} + +/// Format the help information for `command` as Markdown. +pub fn help_markdown() -> String { + let command = C::command(); + help_markdown_command(&command) +} + +/// Format the help information for `command` as Markdown, with custom options. +pub fn help_markdown_custom(options: &MarkdownOptions) -> String { + let command = C::command(); + help_markdown_command_custom(&command, options) +} + +/// Format the help information for `command` as Markdown. +pub fn help_markdown_command(command: &clap::Command) -> String { + help_markdown_command_custom(command, &Default::default()) +} + +/// Format the help information for `command` as Markdown, with custom options. +pub fn help_markdown_command_custom(command: &clap::Command, options: &MarkdownOptions) -> String { + let mut buffer = String::with_capacity(100); + write_help_markdown(&mut buffer, command, options); + buffer +} + +/// Format the help information for `command` as Markdown and print it. +/// +/// Output is printed to the standard output. +#[allow(clippy::disallowed_macros)] +pub fn print_help_markdown() { + let command = C::command(); + let mut buffer = String::with_capacity(100); + write_help_markdown(&mut buffer, &command, &Default::default()); + println!("{buffer}"); +} + +fn write_help_markdown(buffer: &mut String, command: &clap::Command, options: &MarkdownOptions) { + let title_name = get_canonical_name(command); + + let title = match options.title { + Some(ref title) => title.to_owned(), + None => format!("Command-Line Help for `{title_name}`"), + }; + writeln!(buffer, "# {title}\n",).unwrap(); + + writeln!( + buffer, + "This document contains the help content for the `{title_name}` command-line program.\n", + ) + .unwrap(); + + // Write the version if available (PR #52) + if let Some(version) = command.get_version() { + let version_str = version.to_string(); + + if version_str.contains('\n') { + // Multi-line version: use a code block + writeln!(buffer, "**Version:**\n\n```\n{}\n```\n", version_str.trim()).unwrap(); + } else { + // Single-line version: use inline code + writeln!(buffer, "**Version:** `{version_str}`\n").unwrap(); + } + } + + // Write the table of contents + if options.show_table_of_contents { + writeln!(buffer, "**Command Overview:**\n").unwrap(); + build_table_of_contents_markdown(buffer, Vec::new(), command, 0).unwrap(); + writeln!(buffer).unwrap(); + } + + // Write the commands/subcommands sections + build_command_markdown(buffer, Vec::new(), command, 0, options).unwrap(); + + // Write the footer + if options.show_footer { + write!( + buffer, + r#"
+ + + This document was generated automatically by + clap-markdown. + +"# + ) + .unwrap(); + } +} + +fn build_table_of_contents_markdown( + buffer: &mut String, + parent_command_path: Vec, + command: &clap::Command, + _depth: usize, +) -> std::fmt::Result { + // Don't document commands marked with `clap(hide = true)` + if command.is_hide_set() { + return Ok(()); + } + + let title_name = get_canonical_name(command); + + let command_path = { + let mut command_path = parent_command_path; + command_path.push(title_name); + command_path + }; + + writeln!(buffer, "* [`{}`↴](#{})", command_path.join(" "), command_path.join("-"),)?; + + for subcommand in command.get_subcommands() { + build_table_of_contents_markdown(buffer, command_path.clone(), subcommand, _depth + 1)?; + } + + Ok(()) +} + +fn build_command_markdown( + buffer: &mut String, + parent_command_path: Vec, + command: &clap::Command, + _depth: usize, + options: &MarkdownOptions, +) -> std::fmt::Result { + // Don't document commands marked with `clap(hide = true)` + if command.is_hide_set() { + return Ok(()); + } + + let title_name = get_canonical_name(command); + + let command_path = { + let mut command_path = parent_command_path.clone(); + command_path.push(title_name); + command_path + }; + + // Write the markdown heading + writeln!(buffer, "## `{}`\n", command_path.join(" "))?; + + if let Some(long_about) = command.get_long_about() { + writeln!(buffer, "{long_about}\n")?; + } else if let Some(about) = command.get_about() { + writeln!(buffer, "{about}\n")?; + } + + if let Some(help) = command.get_before_long_help() { + writeln!(buffer, "{help}\n")?; + } else if let Some(help) = command.get_before_help() { + writeln!(buffer, "{help}\n")?; + } + + writeln!( + buffer, + "**Usage:** `{}{}`\n", + if parent_command_path.is_empty() { + String::new() + } else { + let mut s = parent_command_path.join(" "); + s.push(' '); + s + }, + command.clone().render_usage().to_string().replace("Usage: ", "") + )?; + + if options.show_aliases { + let aliases = command.get_visible_aliases().collect::>(); + if let Some(aliases_str) = get_alias_string(&aliases) { + writeln!( + buffer, + "**{}:** {aliases_str}\n", + pluralize(aliases.len(), "Command Alias", "Command Aliases") + )?; + } + } + + if let Some(help) = command.get_after_long_help() { + writeln!(buffer, "{help}\n")?; + } else if let Some(help) = command.get_after_help() { + writeln!(buffer, "{help}\n")?; + } + + // Subcommands + if command.get_subcommands().next().is_some() { + writeln!(buffer, "###### **Subcommands:**\n")?; + + for subcommand in command.get_subcommands() { + if subcommand.is_hide_set() { + continue; + } + + let title_name = get_canonical_name(subcommand); + let about = match subcommand.get_about() { + Some(about) => about.to_string(), + None => String::new(), + }; + + writeln!(buffer, "* `{title_name}` — {about}",)?; + } + + writeln!(buffer)?; + } + + // Arguments (positional) + if command.get_positionals().next().is_some() { + writeln!(buffer, "###### **Arguments:**\n")?; + + for pos_arg in command.get_positionals() { + write_arg_markdown(buffer, pos_arg)?; + } + + writeln!(buffer)?; + } + + // Options (grouped by help heading) - PR #48 + let non_pos: Vec<_> = + command.get_arguments().filter(|arg| !arg.is_positional() && !arg.is_hide_set()).collect(); + + if !non_pos.is_empty() { + // Group arguments by help heading + let mut grouped_args: BTreeMap<&str, Vec<&clap::Arg>> = BTreeMap::new(); + + for arg in non_pos { + let heading = arg.get_help_heading().unwrap_or("Options"); + grouped_args.entry(heading).or_default().push(arg); + } + + // Write each group with its heading + for (heading, args) in grouped_args { + writeln!(buffer, "###### **{heading}:**\n")?; + + for arg in args { + write_arg_markdown(buffer, arg)?; + } + + writeln!(buffer)?; + } + } + + // Include extra space between commands + write!(buffer, "\n\n")?; + + for subcommand in command.get_subcommands() { + build_command_markdown(buffer, command_path.clone(), subcommand, _depth + 1, options)?; + } + + Ok(()) +} + +fn write_arg_markdown(buffer: &mut String, arg: &clap::Arg) -> fmt::Result { + // Markdown list item + write!(buffer, "* ")?; + + let value_name: String = match arg.get_value_names() { + Some([name, ..]) => name.as_str().to_owned(), + Some([]) => unreachable!("clap Arg::get_value_names() returned Some(..) of empty list"), + None => arg.get_id().to_string().to_ascii_uppercase(), + }; + + match (arg.get_short(), arg.get_long()) { + (Some(short), Some(long)) => { + if arg.get_action().takes_values() { + write!(buffer, "`-{short}`, `--{long} <{value_name}>`")? + } else { + write!(buffer, "`-{short}`, `--{long}`")? + } + } + (Some(short), None) => { + if arg.get_action().takes_values() { + write!(buffer, "`-{short} <{value_name}>`")? + } else { + write!(buffer, "`-{short}`")? + } + } + (None, Some(long)) => { + if arg.get_action().takes_values() { + write!(buffer, "`--{long} <{value_name}>`")? + } else { + write!(buffer, "`--{long}`")? + } + } + (None, None) => { + debug_assert!( + arg.is_positional(), + "unexpected non-positional Arg with neither short nor long name: {arg:?}" + ); + write!(buffer, "`<{value_name}>`",)?; + } + } + + if let Some(aliases) = arg.get_visible_aliases().as_deref() + && let Some(aliases_str) = get_alias_string(aliases) + { + write!(buffer, " [{}: {aliases_str}]", pluralize(aliases.len(), "alias", "aliases"))?; + } + + if let Some(help) = arg.get_long_help() { + buffer.push_str(&indent(&help.to_string(), " — ", " ")) + } else if let Some(short_help) = arg.get_help() { + writeln!(buffer, " — {short_help}")?; + } else { + writeln!(buffer)?; + } + + // Arg default values + if !arg.get_default_values().is_empty() { + let default_values: String = arg + .get_default_values() + .iter() + .map(|value| format!("`{}`", value.to_string_lossy())) + .collect::>() + .join(", "); + + if arg.get_default_values().len() > 1 { + writeln!(buffer, "\n Default values: {default_values}")?; + } else { + writeln!(buffer, "\n Default value: {default_values}")?; + } + } + + // Arg possible values + let possible_values: Vec = + arg.get_possible_values().into_iter().filter(|pv| !pv.is_hide_set()).collect(); + + if !possible_values.is_empty() && !matches!(arg.get_action(), clap::ArgAction::SetTrue) { + let any_have_help: bool = possible_values.iter().any(|pv| pv.get_help().is_some()); + + if any_have_help { + let text: String = possible_values + .iter() + .map(|pv| match pv.get_help() { + Some(help) => { + format!(" - `{}`:\n {}\n", pv.get_name(), help) + } + None => format!(" - `{}`\n", pv.get_name()), + }) + .collect::>() + .join(""); + + writeln!(buffer, "\n Possible values:\n{text}")?; + } else { + let text: String = possible_values + .iter() + .map(|pv| format!("`{}`", pv.get_name())) + .collect::>() + .join(", "); + + writeln!(buffer, "\n Possible values: {text}\n")?; + } + } + + // Arg environment variable (PR #50) + if !arg.is_hide_env_set() + && let Some(env) = arg.get_env() + { + writeln!(buffer, "\n Environment variable: `{}`", env.to_string_lossy())?; + } + + Ok(()) +} + +/// Utility function to get the canonical name of a command. +fn get_canonical_name(command: &clap::Command) -> String { + command + .get_display_name() + .or_else(|| command.get_bin_name()) + .map(|name| name.to_owned()) + .unwrap_or_else(|| command.get_name().to_owned()) +} + +/// Indents non-empty lines. The output always ends with a newline. +fn indent(s: &str, first: &str, rest: &str) -> String { + if s.is_empty() { + return "\n".to_string(); + } + let mut result = String::new(); + let mut first_line = true; + + for line in s.lines() { + if !line.is_empty() { + result.push_str(if first_line { first } else { rest }); + result.push_str(line); + first_line = false; + } + result.push('\n'); + } + result +} + +fn get_alias_string(aliases: &[&str]) -> Option { + if aliases.is_empty() { + return None; + } + + Some(aliases.iter().map(|alias| format!("`{alias}`")).collect::>().join(", ")) +} + +fn pluralize<'a>(count: usize, singular: &'a str, plural: &'a str) -> &'a str { + if count == 1 { singular } else { plural } +} + +#[cfg(test)] +mod tests { + use super::*; + use clap::{Arg, Command}; + use pretty_assertions::assert_eq; + + #[test] + fn test_indent() { + assert_eq!(&indent("Header\n\nMore info", "___", "~~~~"), "___Header\n\n~~~~More info\n"); + assert_eq!( + &indent("Header\n\nMore info\n", "___", "~~~~"), + &indent("Header\n\nMore info", "___", "~~~~"), + ); + assert_eq!(&indent("", "___", "~~~~"), "\n"); + assert_eq!(&indent("\n", "___", "~~~~"), "\n"); + } + + #[test] + fn test_version_output() { + let app = Command::new("test-app").version("1.2.3").about("A test application"); + + let markdown = + help_markdown_command_custom(&app, &MarkdownOptions::new().show_footer(false)); + + assert!(markdown.contains("**Version:** `1.2.3`"), "Should contain version"); + } + + #[test] + fn test_multiline_version() { + let multi_line_version = "my-cli 1.2.3 (abc123)\nmy-lib 2.0.0 (789xyz)"; + + let app = Command::new("my-cli").version(multi_line_version).about("Multi-version CLI"); + + let markdown = + help_markdown_command_custom(&app, &MarkdownOptions::new().show_footer(false)); + + assert!(markdown.contains("**Version:**\n\n```"), "Should use code block for multi-line"); + } + + #[test] + fn test_env_var_output() { + let app = Command::new("env-test").about("Test env var output").arg( + Arg::new("config") + .short('c') + .long("config") + .env("CONFIG_PATH") + .help("Path to config file"), + ); + + let markdown = + help_markdown_command_custom(&app, &MarkdownOptions::new().show_footer(false)); + + assert!( + markdown.contains("Environment variable: `CONFIG_PATH`"), + "Should show env var. Output: {markdown}" + ); + } + + #[test] + fn test_grouped_options() { + let app = Command::new("grouped-app") + .about("Test app with grouped options") + .arg( + Arg::new("verbose") + .short('v') + .long("verbose") + .help("Enable verbose output") + .help_heading("General Options") + .action(clap::ArgAction::SetTrue), + ) + .arg( + Arg::new("input") + .short('i') + .long("input") + .help("Input file") + .help_heading("File Options") + .value_name("FILE"), + ) + .arg( + Arg::new("format") + .short('f') + .long("format") + .help("Output format") + .value_name("FORMAT"), + ); + + let markdown = + help_markdown_command_custom(&app, &MarkdownOptions::new().show_footer(false)); + + assert!(markdown.contains("###### **File Options:**"), "Should have File Options heading"); + assert!( + markdown.contains("###### **General Options:**"), + "Should have General Options heading" + ); + assert!(markdown.contains("###### **Options:**"), "Should have default Options heading"); + } + + #[test] + fn test_no_grouped_options_backward_compatibility() { + let app = Command::new("simple-app") + .about("Test app without grouped options") + .arg( + Arg::new("verbose") + .short('v') + .long("verbose") + .help("Enable verbose output") + .action(clap::ArgAction::SetTrue), + ) + .arg( + Arg::new("output").short('o').long("output").help("Output file").value_name("FILE"), + ); + + let markdown = + help_markdown_command_custom(&app, &MarkdownOptions::new().show_footer(false)); + + assert!(markdown.contains("###### **Options:**"), "Should have default Options heading"); + assert!(markdown.contains("`-v`, `--verbose`"), "Should have verbose option"); + assert!(markdown.contains("`-o`, `--output `"), "Should have output option"); + } +} diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index d9acf1de83d09..e1ec43c33df19 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -14,6 +14,7 @@ workspace = true [dependencies] foundry-block-explorers.workspace = true +foundry-cli-markdown.workspace = true foundry-common.workspace = true foundry-config.workspace = true foundry-evm.workspace = true diff --git a/crates/cli/src/handler.rs b/crates/cli/src/handler.rs index 020b7e953068f..763466d21185d 100644 --- a/crates/cli/src/handler.rs +++ b/crates/cli/src/handler.rs @@ -1,5 +1,4 @@ use eyre::EyreHandler; -use itertools::Itertools; use std::{error::Error, fmt}; /// A custom context type for Foundry specific error reporting via `eyre`. @@ -23,8 +22,7 @@ impl Handler { impl EyreHandler for Handler { fn display(&self, error: &(dyn Error + 'static), f: &mut fmt::Formatter<'_>) -> fmt::Result { - use fmt::Display; - foundry_common::errors::dedup_chain(error).into_iter().format("; ").fmt(f) + f.write_str(&foundry_common::errors::display_chain(error)) } fn debug(&self, error: &(dyn Error + 'static), f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/crates/cli/src/opts/global.rs b/crates/cli/src/opts/global.rs index 8bfc13c00001f..fee75a5d34e87 100644 --- a/crates/cli/src/opts/global.rs +++ b/crates/cli/src/opts/global.rs @@ -51,6 +51,17 @@ pub struct GlobalArgs { } impl GlobalArgs { + /// Check if `--markdown-help` was passed and print CLI reference as Markdown, then exit. + /// + /// This must be called **before** parsing arguments, since commands with required + /// subcommands would fail parsing before the flag is checked. + pub fn check_markdown_help() { + if std::env::args().any(|arg| arg == "--markdown-help") { + foundry_cli_markdown::print_help_markdown::(); + std::process::exit(0); + } + } + /// Initialize the global options. pub fn init(&self) -> eyre::Result<()> { // Set the global shell. diff --git a/crates/cli/src/utils/mod.rs b/crates/cli/src/utils/mod.rs index f127010674aaf..dff85f9457fa7 100644 --- a/crates/cli/src/utils/mod.rs +++ b/crates/cli/src/utils/mod.rs @@ -115,33 +115,8 @@ pub fn get_provider_with_curl(config: &Config, curl_mode: bool) -> Result Result { - let url = config.get_rpc_url_or_localhost_http()?; - let mut builder = ProviderBuilder::new(url.as_ref()); - - builder = builder.accept_invalid_certs(config.eth_rpc_accept_invalid_certs); - builder = builder.curl_mode(curl_mode); - - if let Ok(chain) = config.chain.unwrap_or_default().try_into() { - builder = builder.chain(chain); - } - - if let Some(jwt) = config.get_rpc_jwt_secret()? { - builder = builder.jwt(jwt.as_ref()); - } - - if let Some(rpc_timeout) = config.eth_rpc_timeout { - builder = builder.timeout(Duration::from_secs(rpc_timeout)); - } - - if let Some(rpc_headers) = config.eth_rpc_headers.clone() { - builder = builder.headers(rpc_headers); - } - - Ok(builder) + ProviderBuilder::from_config(config).map(|builder| builder.curl_mode(curl_mode)) } pub async fn get_chain

(chain: Option, provider: P) -> Result diff --git a/crates/common/Cargo.toml b/crates/common/Cargo.toml index 154bbc5cc53ca..75776743d1132 100644 --- a/crates/common/Cargo.toml +++ b/crates/common/Cargo.toml @@ -16,6 +16,7 @@ workspace = true foundry-block-explorers = { workspace = true, features = ["foundry-compilers"] } foundry-common-fmt.workspace = true foundry-compilers.workspace = true +foundry-config.workspace = true alloy-chains.workspace = true alloy-dyn-abi = { workspace = true, features = ["arbitrary", "eip712"] } diff --git a/crates/common/src/provider/mod.rs b/crates/common/src/provider/mod.rs index 5d4c4657362e4..a098c33a34827 100644 --- a/crates/common/src/provider/mod.rs +++ b/crates/common/src/provider/mod.rs @@ -8,16 +8,19 @@ use crate::{ provider::{curl_transport::CurlTransport, runtime_transport::RuntimeTransportBuilder}, }; use alloy_chains::NamedChain; +use alloy_network::{Network, NetworkWallet}; use alloy_provider::{ Identity, ProviderBuilder as AlloyProviderBuilder, RootProvider, - fillers::{ChainIdFiller, FillProvider, GasFiller, JoinFill, NonceFiller, WalletFiller}, + fillers::{FillProvider, JoinFill, RecommendedFillers, WalletFiller}, network::{AnyNetwork, EthereumWallet}, }; use alloy_rpc_client::ClientBuilder; use alloy_transport::{layers::RetryBackoffLayer, utils::guess_local_url}; use eyre::{Result, WrapErr}; +use foundry_config::Config; use reqwest::Url; use std::{ + marker::PhantomData, net::SocketAddr, path::{Path, PathBuf}, str::FromStr, @@ -36,20 +39,8 @@ const POLL_INTERVAL_BLOCK_TIME_SCALE_FACTOR: f32 = 0.6; pub type RetryProvider = RootProvider; /// Helper type alias for a retry provider with a signer -pub type RetryProviderWithSigner = FillProvider< - JoinFill< - JoinFill< - Identity, - JoinFill< - GasFiller, - JoinFill< - alloy_provider::fillers::BlobGasFiller, - JoinFill, - >, - >, - >, - WalletFiller, - >, +pub type RetryProviderWithSigner = FillProvider< + JoinFill::RecommendedFillers>, WalletFiller>, RootProvider, N, >; @@ -84,8 +75,10 @@ pub fn try_get_http_provider(builder: impl AsRef) -> Result } /// Helper type to construct a `RetryProvider` +/// +/// This builder is generic over the network type `N`, defaulting to `AnyNetwork`. #[derive(Debug)] -pub struct ProviderBuilder { +pub struct ProviderBuilder { // Note: this is a result, so we can easily chain builder calls url: Result, chain: NamedChain, @@ -104,10 +97,12 @@ pub struct ProviderBuilder { no_proxy: bool, /// Whether to output curl commands instead of making requests. curl_mode: bool, + /// Phantom data for the network type. + _network: PhantomData, } -impl ProviderBuilder { - /// Creates a new builder instance +impl ProviderBuilder { + /// Creates a new ProviderBuilder helper instance. pub fn new(url_str: &str) -> Self { // a copy is needed for the next lines to work let mut url_str = url_str; @@ -156,9 +151,38 @@ impl ProviderBuilder { accept_invalid_certs: false, no_proxy: false, curl_mode: false, + _network: PhantomData, } } + /// Constructs a [ProviderBuilder] instantiated using [Config] values. + /// + /// Defaults to `http://localhost:8545` and `Mainnet`. + pub fn from_config(config: &Config) -> Result { + let url = config.get_rpc_url_or_localhost_http()?; + let mut builder = Self::new(url.as_ref()); + + builder = builder.accept_invalid_certs(config.eth_rpc_accept_invalid_certs); + + if let Ok(chain) = config.chain.unwrap_or_default().try_into() { + builder = builder.chain(chain); + } + + if let Some(jwt) = config.get_rpc_jwt_secret()? { + builder = builder.jwt(jwt.as_ref()); + } + + if let Some(rpc_timeout) = config.eth_rpc_timeout { + builder = builder.timeout(Duration::from_secs(rpc_timeout)); + } + + if let Some(rpc_headers) = config.eth_rpc_headers.clone() { + builder = builder.headers(rpc_headers); + } + + Ok(builder) + } + /// Enables a request timeout. /// /// The timeout is applied from when the request starts connecting until the @@ -278,7 +302,7 @@ impl ProviderBuilder { } /// Constructs the `RetryProvider` taking all configs into account. - pub fn build(self) -> Result { + pub fn build(self) -> Result> { let Self { url, chain, @@ -292,6 +316,7 @@ impl ProviderBuilder { accept_invalid_certs, no_proxy, curl_mode, + .. } = self; let url = url?; @@ -303,7 +328,7 @@ impl ProviderBuilder { let transport = CurlTransport::new(url).with_headers(headers).with_jwt(jwt); let client = ClientBuilder::default().layer(retry_layer).transport(transport, is_local); - let provider = AlloyProviderBuilder::<_, _, AnyNetwork>::default() + let provider = AlloyProviderBuilder::<_, _, N>::default() .connect_provider(RootProvider::new(client)); return Ok(provider); @@ -330,14 +355,22 @@ impl ProviderBuilder { ); } - let provider = AlloyProviderBuilder::<_, _, AnyNetwork>::default() - .connect_provider(RootProvider::new(client)); + let provider = + AlloyProviderBuilder::<_, _, N>::default().connect_provider(RootProvider::new(client)); Ok(provider) } +} +impl ProviderBuilder { /// Constructs the `RetryProvider` with a wallet. - pub fn build_with_wallet(self, wallet: EthereumWallet) -> Result { + pub fn build_with_wallet + Clone>( + self, + wallet: W, + ) -> Result> + where + N: RecommendedFillers, + { let Self { url, chain, @@ -351,6 +384,7 @@ impl ProviderBuilder { accept_invalid_certs, no_proxy, curl_mode, + .. } = self; let url = url?; @@ -362,7 +396,7 @@ impl ProviderBuilder { let transport = CurlTransport::new(url).with_headers(headers).with_jwt(jwt); let client = ClientBuilder::default().layer(retry_layer).transport(transport, is_local); - let provider = AlloyProviderBuilder::<_, _, AnyNetwork>::default() + let provider = AlloyProviderBuilder::<_, _, N>::default() .with_recommended_fillers() .wallet(wallet) .connect_provider(RootProvider::new(client)); @@ -392,7 +426,7 @@ impl ProviderBuilder { ); } - let provider = AlloyProviderBuilder::<_, _, AnyNetwork>::default() + let provider = AlloyProviderBuilder::<_, _, N>::default() .with_recommended_fillers() .wallet(wallet) .connect_provider(RootProvider::new(client)); @@ -426,7 +460,7 @@ mod tests { #[test] fn can_auto_correct_missing_prefix() { - let builder = ProviderBuilder::new("localhost:8545"); + let builder = ProviderBuilder::::new("localhost:8545"); assert!(builder.url.is_ok()); let url = builder.url.unwrap(); diff --git a/crates/config/src/lint.rs b/crates/config/src/lint.rs index c726e3ecc8f5b..25094ead98cf8 100644 --- a/crates/config/src/lint.rs +++ b/crates/config/src/lint.rs @@ -28,8 +28,8 @@ pub struct LinterConfig { /// Configurable patterns that should be excluded when performing `mixedCase` lint checks. /// - /// Default's to ["ERC", "URI"] to allow common names like `rescueERC20`, `ERC721TokenReceiver` - /// or `tokenURI`. + /// Defaults to common abbreviations: `ERC`, `URI`, `ID`, `URL`, `API`, `JSON`, `XML`, `HTML`, + /// `HTTP`, `HTTPS`. This allows names like `marketID`, `tokenURI`, `apiURL`, `parseJSON`, etc. pub mixed_case_exceptions: Vec, } @@ -40,7 +40,18 @@ impl Default for LinterConfig { severity: vec![Severity::High, Severity::Med, Severity::Low], exclude_lints: Vec::new(), ignore: Vec::new(), - mixed_case_exceptions: vec!["ERC".to_string(), "URI".to_string()], + mixed_case_exceptions: vec![ + "ERC".to_string(), + "URI".to_string(), + "ID".to_string(), + "URL".to_string(), + "API".to_string(), + "JSON".to_string(), + "XML".to_string(), + "HTML".to_string(), + "HTTP".to_string(), + "HTTPS".to_string(), + ], } } } diff --git a/crates/config/src/utils.rs b/crates/config/src/utils.rs index 52e751cd2ca03..624dd5a35f81b 100644 --- a/crates/config/src/utils.rs +++ b/crates/config/src/utils.rs @@ -213,7 +213,7 @@ where deserialize_u64_or_max(deserializer)?.try_into().map_err(D::Error::custom) } -/// Deserialize into `U256` from either a `u64` or a `U256` hex string. +/// Deserialize into `U256` from either a `u64`, a `U256` hex string, or a decimal string. pub fn deserialize_u64_to_u256<'de, D>(deserializer: D) -> Result where D: Deserializer<'de>, @@ -223,11 +223,16 @@ where enum NumericValue { U256(U256), U64(u64), + String(String), } match NumericValue::deserialize(deserializer)? { NumericValue::U64(n) => Ok(U256::from(n)), NumericValue::U256(n) => Ok(n), + NumericValue::String(s) => { + // Handle decimal strings (e.g., "18446744073709551615") + U256::from_str(&s).map_err(D::Error::custom) + } } } diff --git a/crates/debugger/src/node.rs b/crates/debugger/src/node.rs index f7b18a978a4f4..e74ae58d66323 100644 --- a/crates/debugger/src/node.rs +++ b/crates/debugger/src/node.rs @@ -14,6 +14,8 @@ pub struct DebugNode { pub kind: CallKind, /// Calldata of the call. pub calldata: Bytes, + /// The gas limit of the call. + pub gas_limit: u64, /// The debug steps. pub steps: Vec, } @@ -25,8 +27,9 @@ impl DebugNode { kind: CallKind, steps: Vec, calldata: Bytes, + gas_limit: u64, ) -> Self { - Self { address, kind, steps, calldata } + Self { address, kind, steps, calldata, gas_limit } } } @@ -78,7 +81,7 @@ pub fn flatten_call_trace(arena: CallTraceArena, out: &mut Vec) { let call = &arena_nodes[pending.node_idx].trace; let calldata = if call.kind.is_any_create() { Bytes::new() } else { call.data.clone() }; - let node = DebugNode::new(call.address, call.kind, steps, calldata); + let node = DebugNode::new(call.address, call.kind, steps, calldata, call.gas_limit); out.push(node); } diff --git a/crates/debugger/src/tui/draw.rs b/crates/debugger/src/tui/draw.rs index 6badd441fdb94..daf2d01d1da84 100644 --- a/crates/debugger/src/tui/draw.rs +++ b/crates/debugger/src/tui/draw.rs @@ -372,10 +372,11 @@ impl TUIContext<'_> { .collect::>(); let title = format!( - "Address: {} | PC: {} | Gas used in call: {}", + "Address: {} | PC: {} | Gas used: {} | Gas refund: {}", self.address(), self.current_step().pc, - self.current_step().gas_used, + self.debug_call().gas_limit - self.current_step().gas_remaining, + self.current_step().gas_refund_counter ); let block = Block::default().title(title).borders(Borders::ALL); let list = List::new(items) diff --git a/crates/evm/evm/src/executors/fuzz/mod.rs b/crates/evm/evm/src/executors/fuzz/mod.rs index 1d6933ee5e981..5a6cc4e91bafb 100644 --- a/crates/evm/evm/src/executors/fuzz/mod.rs +++ b/crates/evm/evm/src/executors/fuzz/mod.rs @@ -280,7 +280,7 @@ impl FuzzedExecutor { if success { Ok(FuzzOutcome::Case(CaseOutcome { - case: FuzzCase { calldata, gas: call.gas_used, stipend: call.stipend }, + case: FuzzCase { gas: call.gas_used, stipend: call.stipend }, traces: call.traces, coverage: call.line_coverage, breakpoints, diff --git a/crates/evm/evm/src/executors/invariant/mod.rs b/crates/evm/evm/src/executors/invariant/mod.rs index db992516850a1..0aa09f7fc406c 100644 --- a/crates/evm/evm/src/executors/invariant/mod.rs +++ b/crates/evm/evm/src/executors/invariant/mod.rs @@ -470,11 +470,9 @@ impl<'a> InvariantExecutor<'a> { { warn!(target: "forge::test", "{error}"); } - current_run.fuzz_runs.push(FuzzCase { - calldata: tx.call_details.calldata.clone(), - gas: call_result.gas_used, - stipend: call_result.stipend, - }); + current_run + .fuzz_runs + .push(FuzzCase { gas: call_result.gas_used, stipend: call_result.stipend }); // Determine if test can continue or should exit. // Check invariants based on check_interval to improve deep run performance. diff --git a/crates/evm/fuzz/src/lib.rs b/crates/evm/fuzz/src/lib.rs index 1308be9b40241..44d71fb6deee3 100644 --- a/crates/evm/fuzz/src/lib.rs +++ b/crates/evm/fuzz/src/lib.rs @@ -317,8 +317,6 @@ impl FuzzTestResult { /// Data of a single fuzz test case #[derive(Clone, Debug, Default, Serialize, Deserialize)] pub struct FuzzCase { - /// The calldata used for this fuzz test - pub calldata: Bytes, /// Consumed gas pub gas: u64, /// The initial gas stipend for the transaction diff --git a/crates/evm/traces/src/folded_stack_trace.rs b/crates/evm/traces/src/folded_stack_trace.rs index 80ac8a8dcb620..2b4e58b8665a7 100644 --- a/crates/evm/traces/src/folded_stack_trace.rs +++ b/crates/evm/traces/src/folded_stack_trace.rs @@ -5,20 +5,26 @@ use revm_inspectors::tracing::{ }; /// Builds a folded stack trace from a call trace arena. -pub fn build(arena: &CallTraceArena) -> Vec { - let mut fst = EvmFoldedStackTraceBuilder::default(); +pub fn build(arena: &CallTraceArena, isolate: bool) -> Vec { + let mut fst = EvmFoldedStackTraceBuilder::new(isolate); fst.process_call_node(arena.nodes(), 0); fst.build() } /// Wrapper for building a folded stack trace using EVM call trace node. -#[derive(Default)] pub struct EvmFoldedStackTraceBuilder { + /// Trace produced in isolate mode, meaning refund needs to be reversed at the depth=1 + /// frame for consistent gas values. + isolate: bool, /// Raw folded stack trace builder. fst: FoldedStackTraceBuilder, } impl EvmFoldedStackTraceBuilder { + pub fn new(isolate: bool) -> Self { + Self { isolate, fst: FoldedStackTraceBuilder::default() } + } + /// Returns the folded stack trace. pub fn build(self) -> Vec { self.fst.build() @@ -57,7 +63,13 @@ impl EvmFoldedStackTraceBuilder { } }; - self.fst.enter(func_name, node.trace.gas_used as i64); + let mut gas_used = node.trace.gas_used; + let max_refund_adjust_depth = if self.isolate { 1 } else { 0 }; + if node.trace.depth <= max_refund_adjust_depth { + gas_used += node.trace.gas_refund_counter; + } + + self.fst.enter(func_name, gas_used); // Track internal function step exits to do in this call context. let mut step_exits = vec![]; @@ -99,8 +111,8 @@ impl EvmFoldedStackTraceBuilder { if let Some(decoded_step) = &step.decoded { match decoded_step.as_ref() { DecodedTraceStep::InternalCall(decoded_internal_call, step_end_idx) => { - let gas_used = steps[*step_end_idx].gas_used.saturating_sub(step.gas_used); - self.fst.enter(decoded_internal_call.func_name.clone(), gas_used as i64); + let gas_used = step.gas_remaining - steps[*step_end_idx].gas_remaining; + self.fst.enter(decoded_internal_call.func_name.clone(), gas_used); step_exits.push(*step_end_idx); } DecodedTraceStep::Line(_) => {} @@ -158,13 +170,13 @@ pub struct FoldedStackTraceBuilder { struct TraceEntry { /// Names of all functions in the call stack of this trace. names: Vec, - /// Gas consumed by this function, allowed to be negative due to refunds. - gas: i64, + /// Gas consumed by this function, not including refunds. + gas: u64, } impl FoldedStackTraceBuilder { /// Enter execution of a function call that consumes `gas`. - pub fn enter(&mut self, label: String, gas: i64) { + pub fn enter(&mut self, label: String, gas: u64) { let mut names = self.traces.last().map(|entry| entry.names.clone()).unwrap_or_default(); while self.exits > 0 { @@ -189,7 +201,7 @@ impl FoldedStackTraceBuilder { /// Internal method to build the folded stack trace without subtracting gas consumed by /// the children function calls. - fn build_without_subtraction(&mut self) -> Vec { + pub fn build_without_subtraction(&mut self) -> Vec { let mut lines = Vec::new(); for TraceEntry { names, gas } in &self.traces { lines.push(format!("{} {}", names.join(";"), gas)); diff --git a/crates/fmt/src/state/sol.rs b/crates/fmt/src/state/sol.rs index fd0e5a9e54c0a..540949f51c071 100644 --- a/crates/fmt/src/state/sol.rs +++ b/crates/fmt/src/state/sol.rs @@ -407,7 +407,9 @@ impl<'ast> State<'_, 'ast> { self.block_depth -= 1; } else { if self.print_comments(span.hi(), CommentConfig::skip_ws()).is_some() { - self.zerobreak(); + // Adjust the offset of the trailing break from comment printing + // so the closing brace is not indented + self.s.offset(-self.ind); } else if self.config.bracket_spacing { self.nbsp(); }; diff --git a/crates/fmt/testdata/CommentEmptyLine/fmt.sol b/crates/fmt/testdata/CommentEmptyLine/fmt.sol new file mode 100644 index 0000000000000..a2407017f4be9 --- /dev/null +++ b/crates/fmt/testdata/CommentEmptyLine/fmt.sol @@ -0,0 +1,5 @@ +pragma solidity ^0.8.0; + +contract ProofOfConcept { + // some comment +} diff --git a/crates/fmt/testdata/CommentEmptyLine/original.sol b/crates/fmt/testdata/CommentEmptyLine/original.sol new file mode 100644 index 0000000000000..9c7f35770e9f3 --- /dev/null +++ b/crates/fmt/testdata/CommentEmptyLine/original.sol @@ -0,0 +1,6 @@ +pragma solidity ^0.8.0; + +contract ProofOfConcept { + // some comment + +} diff --git a/crates/fmt/tests/formatter.rs b/crates/fmt/tests/formatter.rs index b0d4ed3bdcd7f..f337b5b3657fa 100644 --- a/crates/fmt/tests/formatter.rs +++ b/crates/fmt/tests/formatter.rs @@ -169,6 +169,7 @@ fmt_tests! { ArrayExpressions, BlockComments, BlockCommentsFunction, + CommentEmptyLine, ConditionalOperatorExpression, ConstructorDefinition, ConstructorModifierStyle, @@ -224,3 +225,28 @@ fmt_tests! { Yul, YulStrings, } + +#[test] +fn test_comment_empty_line_bug() { + init_tracing(); + let source = r#"pragma solidity ^0.8.0; + +contract ProofOfConcept { + // some comment + +} +"#; + + let expected = r#"pragma solidity ^0.8.0; + +contract ProofOfConcept { + // some comment +} +"#; + + let fmt_config = Arc::new(FormatterConfig::default()); + let path = Path::new("test.sol"); + let formatted = format(source, path, fmt_config); + + assert_eq!(formatted, expected, "Formatting mismatch"); +} diff --git a/crates/forge/Cargo.toml b/crates/forge/Cargo.toml index 2142a87c5cbd4..c059fb00e8f0a 100644 --- a/crates/forge/Cargo.toml +++ b/crates/forge/Cargo.toml @@ -35,6 +35,7 @@ foundry-linking.workspace = true comfy-table.workspace = true eyre.workspace = true proptest.workspace = true +rand.workspace = true rayon.workspace = true serde.workspace = true tracing.workspace = true diff --git a/crates/forge/src/args.rs b/crates/forge/src/args.rs index aada974c91b9a..4f55f028a3690 100644 --- a/crates/forge/src/args.rs +++ b/crates/forge/src/args.rs @@ -13,6 +13,8 @@ use foundry_evm::inspectors::cheatcodes::{ForgeContext, set_execution_context}; pub fn run() -> Result<()> { setup()?; + foundry_cli::opts::GlobalArgs::check_markdown_help::(); + let args = Forge::parse(); args.global.init()?; diff --git a/crates/forge/src/cmd/eip712.rs b/crates/forge/src/cmd/eip712.rs index 00a872a1df7a4..5d6b1bace69ca 100644 --- a/crates/forge/src/cmd/eip712.rs +++ b/crates/forge/src/cmd/eip712.rs @@ -84,7 +84,7 @@ impl Eip712Args { if compiler.sess().dcx.has_errors().is_err() { eyre::bail!("{diags}"); } else { - let _ = sh_print!("{diags}"); + let _ = sh_eprint!("{diags}"); } Ok(()) diff --git a/crates/forge/src/cmd/test/mod.rs b/crates/forge/src/cmd/test/mod.rs index a31f227d4d675..a026a80b5231b 100644 --- a/crates/forge/src/cmd/test/mod.rs +++ b/crates/forge/src/cmd/test/mod.rs @@ -43,6 +43,7 @@ use foundry_evm::{ opts::EvmOpts, traces::{backtrace::BacktraceBuilder, identifier::TraceIdentifiers, prune_trace_depth}, }; +use rand::Rng; use regex::Regex; use std::{ collections::{BTreeMap, BTreeSet}, @@ -304,6 +305,12 @@ impl TestArgs { config.invariant.gas_report_samples = 0; } + // Generate a random fuzz seed if none provided, for reproducibility. + config.fuzz.seed = config + .fuzz + .seed + .or_else(|| Some(U256::from_be_bytes(rand::rng().random::<[u8; 32]>()))); + // Create test options from general project settings and compiler output. let should_debug = self.debug; let should_draw = self.flamegraph || self.flamechart; @@ -361,7 +368,7 @@ impl TestArgs { // Decode traces. let decoder = outcome.last_run_decoder.as_ref().unwrap(); decode_trace_arena(arena, decoder).await; - let mut fst = folded_stack_trace::build(arena); + let mut fst = folded_stack_trace::build(arena, self.evm.isolate); let label = if self.flamegraph { "flamegraph" } else { "flamechart" }; let contract = suite_name.split(':').next_back().unwrap(); @@ -429,6 +436,7 @@ impl TestArgs { filter: &ProjectPathsAwareFilter, output: &ProjectCompileOutput, ) -> eyre::Result { + let fuzz_seed = config.fuzz.seed; if self.list { return list(runner, filter); } @@ -504,13 +512,13 @@ impl TestArgs { } }); sh_println!("{}", serde_json::to_string(&results)?)?; - return Ok(TestOutcome::new(Some(runner), results, self.allow_failure)); + return Ok(TestOutcome::new(Some(runner), results, self.allow_failure, fuzz_seed)); } if self.junit { let results = runner.test_collect(filter)?; sh_println!("{}", junit_xml_report(&results, verbosity).to_string()?)?; - return Ok(TestOutcome::new(Some(runner), results, self.allow_failure)); + return Ok(TestOutcome::new(Some(runner), results, self.allow_failure, fuzz_seed)); } let remote_chain = @@ -567,6 +575,7 @@ impl TestArgs { let mut gas_snapshots = BTreeMap::>::new(); let mut outcome = TestOutcome::empty(None, self.allow_failure); + outcome.fuzz_seed = fuzz_seed; let mut any_test_failed = false; let mut backtrace_builder = None; diff --git a/crates/forge/src/gas_report.rs b/crates/forge/src/gas_report.rs index 985febef2b964..a8a1b5bbc10cf 100644 --- a/crates/forge/src/gas_report.rs +++ b/crates/forge/src/gas_report.rs @@ -5,7 +5,9 @@ use crate::{ traces::{CallTraceArena, CallTraceDecoder, CallTraceNode, DecodedCallData}, }; use alloy_primitives::map::HashSet; -use comfy_table::{Cell, Color, Table, modifiers::UTF8_ROUND_CORNERS, presets::ASCII_MARKDOWN}; +use comfy_table::{ + Cell, CellAlignment, Color, Table, modifiers::UTF8_ROUND_CORNERS, presets::ASCII_MARKDOWN, +}; use foundry_common::{TestFunctionExt, calc, shell}; use foundry_evm::traces::CallKind; @@ -213,8 +215,8 @@ impl GasReport { Cell::new("Deployment Size").fg(Color::Cyan), ]); table.add_row(vec![ - Cell::new(contract.gas.to_string()), - Cell::new(contract.size.to_string()), + Cell::new(contract.gas.to_string()).set_alignment(CellAlignment::Right), + Cell::new(contract.size.to_string()).set_alignment(CellAlignment::Right), ]); // Add a blank row to separate deployment info from function info. @@ -237,11 +239,19 @@ impl GasReport { table.add_row(vec![ Cell::new(display_name), - Cell::new(gas_info.min.to_string()).fg(Color::Green), - Cell::new(gas_info.mean.to_string()).fg(Color::Yellow), - Cell::new(gas_info.median.to_string()).fg(Color::Yellow), - Cell::new(gas_info.max.to_string()).fg(Color::Red), - Cell::new(gas_info.calls.to_string()), + Cell::new(gas_info.min.to_string()) + .fg(Color::Green) + .set_alignment(CellAlignment::Right), + Cell::new(gas_info.mean.to_string()) + .fg(Color::Yellow) + .set_alignment(CellAlignment::Right), + Cell::new(gas_info.median.to_string()) + .fg(Color::Yellow) + .set_alignment(CellAlignment::Right), + Cell::new(gas_info.max.to_string()) + .fg(Color::Red) + .set_alignment(CellAlignment::Right), + Cell::new(gas_info.calls.to_string()).set_alignment(CellAlignment::Right), ]); }) }); diff --git a/crates/forge/src/result.rs b/crates/forge/src/result.rs index c8ccdc5bc995d..693bea6f1eeb7 100644 --- a/crates/forge/src/result.rs +++ b/crates/forge/src/result.rs @@ -6,7 +6,7 @@ use crate::{ gas_report::GasReport, }; use alloy_primitives::{ - Address, I256, Log, + Address, I256, Log, U256, map::{AddressHashMap, HashMap}, }; use eyre::Report; @@ -46,6 +46,8 @@ pub struct TestOutcome { pub gas_report: Option, /// The runner used to execute the tests. pub runner: Option, + /// The fuzz seed used for the test run. + pub fuzz_seed: Option, } impl TestOutcome { @@ -54,13 +56,14 @@ impl TestOutcome { runner: Option, results: BTreeMap, allow_failure: bool, + fuzz_seed: Option, ) -> Self { - Self { results, allow_failure, last_run_decoder: None, gas_report: None, runner } + Self { results, allow_failure, last_run_decoder: None, gas_report: None, runner, fuzz_seed } } /// Creates a new empty test outcome. pub fn empty(runner: Option, allow_failure: bool) -> Self { - Self::new(runner, BTreeMap::new(), allow_failure) + Self::new(runner, BTreeMap::new(), allow_failure, None) } /// Returns an iterator over all individual succeeding tests and their names. @@ -130,6 +133,11 @@ impl TestOutcome { self.failures().count() } + /// Returns `true` if any fuzz or invariant test failed. + pub fn has_fuzz_failures(&self) -> bool { + self.failures().any(|(_, t)| t.kind.is_fuzz() || t.kind.is_invariant()) + } + /// Sums up all the durations of all individual test suites. /// /// Note that this is not necessarily the wall clock time of the entire test run. @@ -200,6 +208,17 @@ impl TestOutcome { test_word )?; + // Print seed for fuzz/invariant test failures to enable reproduction. + if let Some(seed) = self.fuzz_seed + && outcome.has_fuzz_failures() + { + sh_println!( + "\nFuzz seed: {} (use {} to reproduce)", + format!("{seed:#x}").cyan(), + "`--fuzz-seed`".cyan() + )?; + } + std::process::exit(1); } @@ -895,6 +914,16 @@ impl Default for TestKind { } impl TestKind { + /// Returns `true` if this is a fuzz test. + pub fn is_fuzz(&self) -> bool { + matches!(self, Self::Fuzz { .. }) + } + + /// Returns `true` if this is an invariant test. + pub fn is_invariant(&self) -> bool { + matches!(self, Self::Invariant { .. }) + } + /// The gas consumed by this test pub fn report(&self) -> TestKindReport { match self { diff --git a/crates/forge/tests/cli/cmd.rs b/crates/forge/tests/cli/cmd.rs index 4594004e7a8d0..0ab26ee567deb 100644 --- a/crates/forge/tests/cli/cmd.rs +++ b/crates/forge/tests/cli/cmd.rs @@ -1630,13 +1630,13 @@ forgetest!(gas_report_all_contracts, |prj, cmd| { +=============================================================================================+ | Deployment Cost | Deployment Size | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| -| 133027 | 394 | | | | | +| 133027 | 394 | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| | | | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |----------------------------------------+-----------------+-------+--------+-------+---------| -| foo | 45656 | 45656 | 45656 | 45656 | 1 | +| foo | 45656 | 45656 | 45656 | 45656 | 1 | ╰----------------------------------------+-----------------+-------+--------+-------+---------╯ ╭------------------------------------------+-----------------+--------+--------+--------+---------╮ @@ -1644,13 +1644,13 @@ forgetest!(gas_report_all_contracts, |prj, cmd| { +=================================================================================================+ | Deployment Cost | Deployment Size | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| -| 133243 | 395 | | | | | +| 133243 | 395 | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| | | | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |------------------------------------------+-----------------+--------+--------+--------+---------| -| baz | 287711 | 287711 | 287711 | 287711 | 1 | +| baz | 287711 | 287711 | 287711 | 287711 | 1 | ╰------------------------------------------+-----------------+--------+--------+--------+---------╯ ╭----------------------------------------+-----------------+-------+--------+-------+---------╮ @@ -1658,13 +1658,13 @@ forgetest!(gas_report_all_contracts, |prj, cmd| { +=============================================================================================+ | Deployment Cost | Deployment Size | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| -| 133027 | 394 | | | | | +| 133027 | 394 | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| | | | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |----------------------------------------+-----------------+-------+--------+-------+---------| -| bar | 67683 | 67683 | 67683 | 67683 | 1 | +| bar | 67683 | 67683 | 67683 | 67683 | 1 | ╰----------------------------------------+-----------------+-------+--------+-------+---------╯ @@ -1735,13 +1735,13 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) +=============================================================================================+ | Deployment Cost | Deployment Size | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| -| 133027 | 394 | | | | | +| 133027 | 394 | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| | | | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |----------------------------------------+-----------------+-------+--------+-------+---------| -| foo | 45656 | 45656 | 45656 | 45656 | 1 | +| foo | 45656 | 45656 | 45656 | 45656 | 1 | ╰----------------------------------------+-----------------+-------+--------+-------+---------╯ ╭------------------------------------------+-----------------+--------+--------+--------+---------╮ @@ -1749,13 +1749,13 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) +=================================================================================================+ | Deployment Cost | Deployment Size | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| -| 133243 | 395 | | | | | +| 133243 | 395 | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| | | | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |------------------------------------------+-----------------+--------+--------+--------+---------| -| baz | 287711 | 287711 | 287711 | 287711 | 1 | +| baz | 287711 | 287711 | 287711 | 287711 | 1 | ╰------------------------------------------+-----------------+--------+--------+--------+---------╯ ╭----------------------------------------+-----------------+-------+--------+-------+---------╮ @@ -1763,13 +1763,13 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) +=============================================================================================+ | Deployment Cost | Deployment Size | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| -| 133027 | 394 | | | | | +| 133027 | 394 | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| | | | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |----------------------------------------+-----------------+-------+--------+-------+---------| -| bar | 67683 | 67683 | 67683 | 67683 | 1 | +| bar | 67683 | 67683 | 67683 | 67683 | 1 | ╰----------------------------------------+-----------------+-------+--------+-------+---------╯ @@ -1840,13 +1840,13 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) +=============================================================================================+ | Deployment Cost | Deployment Size | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| -| 133027 | 394 | | | | | +| 133027 | 394 | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| | | | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |----------------------------------------+-----------------+-------+--------+-------+---------| -| foo | 45656 | 45656 | 45656 | 45656 | 1 | +| foo | 45656 | 45656 | 45656 | 45656 | 1 | ╰----------------------------------------+-----------------+-------+--------+-------+---------╯ ╭------------------------------------------+-----------------+--------+--------+--------+---------╮ @@ -1854,13 +1854,13 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) +=================================================================================================+ | Deployment Cost | Deployment Size | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| -| 133243 | 395 | | | | | +| 133243 | 395 | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| | | | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |------------------------------------------+-----------------+--------+--------+--------+---------| -| baz | 287711 | 287711 | 287711 | 287711 | 1 | +| baz | 287711 | 287711 | 287711 | 287711 | 1 | ╰------------------------------------------+-----------------+--------+--------+--------+---------╯ ╭----------------------------------------+-----------------+-------+--------+-------+---------╮ @@ -1868,13 +1868,13 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) +=============================================================================================+ | Deployment Cost | Deployment Size | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| -| 133027 | 394 | | | | | +| 133027 | 394 | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| | | | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |----------------------------------------+-----------------+-------+--------+-------+---------| -| bar | 67683 | 67683 | 67683 | 67683 | 1 | +| bar | 67683 | 67683 | 67683 | 67683 | 1 | ╰----------------------------------------+-----------------+-------+--------+-------+---------╯ @@ -1948,13 +1948,13 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) +=============================================================================================+ | Deployment Cost | Deployment Size | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| -| 133027 | 394 | | | | | +| 133027 | 394 | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| | | | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |----------------------------------------+-----------------+-------+--------+-------+---------| -| foo | 45656 | 45656 | 45656 | 45656 | 1 | +| foo | 45656 | 45656 | 45656 | 45656 | 1 | ╰----------------------------------------+-----------------+-------+--------+-------+---------╯ ╭------------------------------------------+-----------------+--------+--------+--------+---------╮ @@ -1962,13 +1962,13 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) +=================================================================================================+ | Deployment Cost | Deployment Size | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| -| 133243 | 395 | | | | | +| 133243 | 395 | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| | | | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |------------------------------------------+-----------------+--------+--------+--------+---------| -| baz | 287711 | 287711 | 287711 | 287711 | 1 | +| baz | 287711 | 287711 | 287711 | 287711 | 1 | ╰------------------------------------------+-----------------+--------+--------+--------+---------╯ ╭----------------------------------------+-----------------+-------+--------+-------+---------╮ @@ -1976,13 +1976,13 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) +=============================================================================================+ | Deployment Cost | Deployment Size | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| -| 133027 | 394 | | | | | +| 133027 | 394 | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| | | | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |----------------------------------------+-----------------+-------+--------+-------+---------| -| bar | 67683 | 67683 | 67683 | 67683 | 1 | +| bar | 67683 | 67683 | 67683 | 67683 | 1 | ╰----------------------------------------+-----------------+-------+--------+-------+---------╯ @@ -2060,13 +2060,13 @@ forgetest!(gas_report_some_contracts, |prj, cmd| { +=============================================================================================+ | Deployment Cost | Deployment Size | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| -| 133027 | 394 | | | | | +| 133027 | 394 | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| | | | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |----------------------------------------+-----------------+-------+--------+-------+---------| -| foo | 45656 | 45656 | 45656 | 45656 | 1 | +| foo | 45656 | 45656 | 45656 | 45656 | 1 | ╰----------------------------------------+-----------------+-------+--------+-------+---------╯ @@ -2107,13 +2107,13 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) +=============================================================================================+ | Deployment Cost | Deployment Size | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| -| 133027 | 394 | | | | | +| 133027 | 394 | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| | | | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |----------------------------------------+-----------------+-------+--------+-------+---------| -| bar | 67683 | 67683 | 67683 | 67683 | 1 | +| bar | 67683 | 67683 | 67683 | 67683 | 1 | ╰----------------------------------------+-----------------+-------+--------+-------+---------╯ @@ -2154,13 +2154,13 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) +=================================================================================================+ | Deployment Cost | Deployment Size | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| -| 133243 | 395 | | | | | +| 133243 | 395 | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| | | | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |------------------------------------------+-----------------+--------+--------+--------+---------| -| baz | 287711 | 287711 | 287711 | 287711 | 1 | +| baz | 287711 | 287711 | 287711 | 287711 | 1 | ╰------------------------------------------+-----------------+--------+--------+--------+---------╯ @@ -2209,13 +2209,13 @@ forgetest!(gas_report_ignore_some_contracts, |prj, cmd| { +=================================================================================================+ | Deployment Cost | Deployment Size | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| -| 133243 | 395 | | | | | +| 133243 | 395 | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| | | | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |------------------------------------------+-----------------+--------+--------+--------+---------| -| baz | 287711 | 287711 | 287711 | 287711 | 1 | +| baz | 287711 | 287711 | 287711 | 287711 | 1 | ╰------------------------------------------+-----------------+--------+--------+--------+---------╯ ╭----------------------------------------+-----------------+-------+--------+-------+---------╮ @@ -2223,13 +2223,13 @@ forgetest!(gas_report_ignore_some_contracts, |prj, cmd| { +=============================================================================================+ | Deployment Cost | Deployment Size | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| -| 133027 | 394 | | | | | +| 133027 | 394 | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| | | | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |----------------------------------------+-----------------+-------+--------+-------+---------| -| bar | 67683 | 67683 | 67683 | 67683 | 1 | +| bar | 67683 | 67683 | 67683 | 67683 | 1 | ╰----------------------------------------+-----------------+-------+--------+-------+---------╯ @@ -2290,13 +2290,13 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) +=============================================================================================+ | Deployment Cost | Deployment Size | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| -| 133027 | 394 | | | | | +| 133027 | 394 | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| | | | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |----------------------------------------+-----------------+-------+--------+-------+---------| -| foo | 45656 | 45656 | 45656 | 45656 | 1 | +| foo | 45656 | 45656 | 45656 | 45656 | 1 | ╰----------------------------------------+-----------------+-------+--------+-------+---------╯ ╭------------------------------------------+-----------------+--------+--------+--------+---------╮ @@ -2304,13 +2304,13 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) +=================================================================================================+ | Deployment Cost | Deployment Size | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| -| 133243 | 395 | | | | | +| 133243 | 395 | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| | | | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |------------------------------------------+-----------------+--------+--------+--------+---------| -| baz | 287711 | 287711 | 287711 | 287711 | 1 | +| baz | 287711 | 287711 | 287711 | 287711 | 1 | ╰------------------------------------------+-----------------+--------+--------+--------+---------╯ @@ -2379,13 +2379,13 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) +=============================================================================================+ | Deployment Cost | Deployment Size | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| -| 133027 | 394 | | | | | +| 133027 | 394 | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| | | | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |----------------------------------------+-----------------+-------+--------+-------+---------| -| foo | 45656 | 45656 | 45656 | 45656 | 1 | +| foo | 45656 | 45656 | 45656 | 45656 | 1 | ╰----------------------------------------+-----------------+-------+--------+-------+---------╯ ╭------------------------------------------+-----------------+--------+--------+--------+---------╮ @@ -2393,13 +2393,13 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) +=================================================================================================+ | Deployment Cost | Deployment Size | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| -| 133243 | 395 | | | | | +| 133243 | 395 | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| | | | | | | | |------------------------------------------+-----------------+--------+--------+--------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |------------------------------------------+-----------------+--------+--------+--------+---------| -| baz | 287711 | 287711 | 287711 | 287711 | 1 | +| baz | 287711 | 287711 | 287711 | 287711 | 1 | ╰------------------------------------------+-----------------+--------+--------+--------+---------╯ ╭----------------------------------------+-----------------+-------+--------+-------+---------╮ @@ -2407,13 +2407,13 @@ Ran 3 test suites [ELAPSED]: 3 tests passed, 0 failed, 0 skipped (3 total tests) +=============================================================================================+ | Deployment Cost | Deployment Size | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| -| 133027 | 394 | | | | | +| 133027 | 394 | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| | | | | | | | |----------------------------------------+-----------------+-------+--------+-------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |----------------------------------------+-----------------+-------+--------+-------+---------| -| bar | 67683 | 67683 | 67683 | 67683 | 1 | +| bar | 67683 | 67683 | 67683 | 67683 | 1 | ╰----------------------------------------+-----------------+-------+--------+-------+---------╯ @@ -2542,19 +2542,19 @@ contract CounterTest is DSTest { +=======================================================================================+ | Deployment Cost | Deployment Size | | | | | |----------------------------------+-----------------+-------+--------+-------+---------| -| 172107 | 578 | | | | | +| 172107 | 578 | | | | | |----------------------------------+-----------------+-------+--------+-------+---------| | | | | | | | |----------------------------------+-----------------+-------+--------+-------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |----------------------------------+-----------------+-------+--------+-------+---------| -| a | 2402 | 2402 | 2402 | 2402 | 1 | +| a | 2402 | 2402 | 2402 | 2402 | 1 | |----------------------------------+-----------------+-------+--------+-------+---------| -| b | 2447 | 2447 | 2447 | 2447 | 1 | +| b | 2447 | 2447 | 2447 | 2447 | 1 | |----------------------------------+-----------------+-------+--------+-------+---------| -| setNumber(int256) | 23851 | 33807 | 33807 | 43763 | 2 | +| setNumber(int256) | 23851 | 33807 | 33807 | 43763 | 2 | |----------------------------------+-----------------+-------+--------+-------+---------| -| setNumber(uint256) | 23806 | 33762 | 33762 | 43718 | 2 | +| setNumber(uint256) | 23806 | 33762 | 33762 | 43718 | 2 | ╰----------------------------------+-----------------+-------+--------+-------+---------╯ @@ -2669,15 +2669,15 @@ contract GasReportFallbackTest is Test { +========================================================================================================+ | Deployment Cost | Deployment Size | | | | | |---------------------------------------------------+-----------------+-------+--------+-------+---------| -| 117171 | 471 | | | | | +| 117171 | 471 | | | | | |---------------------------------------------------+-----------------+-------+--------+-------+---------| | | | | | | | |---------------------------------------------------+-----------------+-------+--------+-------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |---------------------------------------------------+-----------------+-------+--------+-------+---------| -| deposit | 21185 | 21185 | 21185 | 21185 | 1 | +| deposit | 21185 | 21185 | 21185 | 21185 | 1 | |---------------------------------------------------+-----------------+-------+--------+-------+---------| -| fallback | 29758 | 29758 | 29758 | 29758 | 1 | +| fallback | 29758 | 29758 | 29758 | 29758 | 1 | ╰---------------------------------------------------+-----------------+-------+--------+-------+---------╯ ╭-----------------------------------------------------+-----------------+------+--------+------+---------╮ @@ -2685,13 +2685,13 @@ contract GasReportFallbackTest is Test { +========================================================================================================+ | Deployment Cost | Deployment Size | | | | | |-----------------------------------------------------+-----------------+------+--------+------+---------| -| 153531 | 494 | | | | | +| 153531 | 494 | | | | | |-----------------------------------------------------+-----------------+------+--------+------+---------| | | | | | | | |-----------------------------------------------------+-----------------+------+--------+------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |-----------------------------------------------------+-----------------+------+--------+------+---------| -| deposit | 3661 | 3661 | 3661 | 3661 | 1 | +| deposit | 3661 | 3661 | 3661 | 3661 | 1 | ╰-----------------------------------------------------+-----------------+------+--------+------+---------╯ @@ -2807,13 +2807,13 @@ Suite result: ok. 1 passed; 0 failed; 0 skipped; [ELAPSED] +=====================================================================================================================+ | Deployment Cost | Deployment Size | | | | | |----------------------------------------------------------------+-----------------+-------+--------+-------+---------| -| 132471 | 396 | | | | | +| 132471 | 396 | | | | | |----------------------------------------------------------------+-----------------+-------+--------+-------+---------| | | | | | | | |----------------------------------------------------------------+-----------------+-------+--------+-------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |----------------------------------------------------------------+-----------------+-------+--------+-------+---------| -| fallback | 43461 | 43461 | 43461 | 43461 | 1 | +| fallback | 43461 | 43461 | 43461 | 43461 | 1 | ╰----------------------------------------------------------------+-----------------+-------+--------+-------+---------╯ @@ -2892,13 +2892,13 @@ contract NestedDeploy is Test { +======================================================================================================+ | Deployment Cost | Deployment Size | | | | | |-------------------------------------------------+-----------------+-------+--------+-------+---------| -| 0 | 132 | | | | | +| 0 | 132 | | | | | |-------------------------------------------------+-----------------+-------+--------+-------+---------| | | | | | | | |-------------------------------------------------+-----------------+-------+--------+-------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |-------------------------------------------------+-----------------+-------+--------+-------+---------| -| w | 21185 | 21185 | 21185 | 21185 | 1 | +| w | 21185 | 21185 | 21185 | 21185 | 1 | ╰-------------------------------------------------+-----------------+-------+--------+-------+---------╯ ╭------------------------------------------+-----------------+------+--------+------+---------╮ @@ -2906,13 +2906,13 @@ contract NestedDeploy is Test { +=============================================================================================+ | Deployment Cost | Deployment Size | | | | | |------------------------------------------+-----------------+------+--------+------+---------| -| 0 | 731 | | | | | +| 0 | 731 | | | | | |------------------------------------------+-----------------+------+--------+------+---------| | | | | | | | |------------------------------------------+-----------------+------+--------+------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |------------------------------------------+-----------------+------+--------+------+---------| -| child | 2681 | 2681 | 2681 | 2681 | 1 | +| child | 2681 | 2681 | 2681 | 2681 | 1 | ╰------------------------------------------+-----------------+------+--------+------+---------╯ ╭-------------------------------------------+-----------------+-----+--------+-----+---------╮ @@ -2920,13 +2920,13 @@ contract NestedDeploy is Test { +============================================================================================+ | Deployment Cost | Deployment Size | | | | | |-------------------------------------------+-----------------+-----+--------+-----+---------| -| 328961 | 1163 | | | | | +| 328961 | 1163 | | | | | |-------------------------------------------+-----------------+-----+--------+-----+---------| | | | | | | | |-------------------------------------------+-----------------+-----+--------+-----+---------| | Function Name | Min | Avg | Median | Max | # Calls | |-------------------------------------------+-----------------+-----+--------+-----+---------| -| child | 525 | 525 | 525 | 525 | 1 | +| child | 525 | 525 | 525 | 525 | 1 | ╰-------------------------------------------+-----------------+-----+--------+-----+---------╯ @@ -3732,17 +3732,17 @@ forgetest_init!(gas_report_include_tests, |prj, cmd| { +=======================================================================================+ | Deployment Cost | Deployment Size | | | | | |----------------------------------+-----------------+-------+--------+-------+---------| -| 156813 | 509 | | | | | +| 156813 | 509 | | | | | |----------------------------------+-----------------+-------+--------+-------+---------| | | | | | | | |----------------------------------+-----------------+-------+--------+-------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |----------------------------------+-----------------+-------+--------+-------+---------| -| increment | 43482 | 43482 | 43482 | 43482 | 1 | +| increment | 43482 | 43482 | 43482 | 43482 | 1 | |----------------------------------+-----------------+-------+--------+-------+---------| -| number | 2424 | 2424 | 2424 | 2424 | 1 | +| number | 2424 | 2424 | 2424 | 2424 | 1 | |----------------------------------+-----------------+-------+--------+-------+---------| -| setNumber | 23784 | 23784 | 23784 | 23784 | 1 | +| setNumber | 23784 | 23784 | 23784 | 23784 | 1 | ╰----------------------------------+-----------------+-------+--------+-------+---------╯ ╭-----------------------------------------+-----------------+--------+--------+--------+---------╮ @@ -3750,15 +3750,15 @@ forgetest_init!(gas_report_include_tests, |prj, cmd| { +================================================================================================+ | Deployment Cost | Deployment Size | | | | | |-----------------------------------------+-----------------+--------+--------+--------+---------| -| 1544498 | 7573 | | | | | +| 1544498 | 7573 | | | | | |-----------------------------------------+-----------------+--------+--------+--------+---------| | | | | | | | |-----------------------------------------+-----------------+--------+--------+--------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |-----------------------------------------+-----------------+--------+--------+--------+---------| -| setUp | 218902 | 218902 | 218902 | 218902 | 1 | +| setUp | 218902 | 218902 | 218902 | 218902 | 1 | |-----------------------------------------+-----------------+--------+--------+--------+---------| -| test_Increment | 51847 | 51847 | 51847 | 51847 | 1 | +| test_Increment | 51847 | 51847 | 51847 | 51847 | 1 | ╰-----------------------------------------+-----------------+--------+--------+--------+---------╯ @@ -3774,21 +3774,21 @@ Ran 1 test suite [ELAPSED]: 1 tests passed, 0 failed, 0 skipped (1 total tests) | src/Counter.sol:Counter Contract | | | | | | |----------------------------------|-----------------|-------|--------|-------|---------| | Deployment Cost | Deployment Size | | | | | -| 156813 | 509 | | | | | +| 156813 | 509 | | | | | | | | | | | | | Function Name | Min | Avg | Median | Max | # Calls | -| increment | 43482 | 43482 | 43482 | 43482 | 1 | -| number | 2424 | 2424 | 2424 | 2424 | 1 | -| setNumber | 23784 | 23784 | 23784 | 23784 | 1 | +| increment | 43482 | 43482 | 43482 | 43482 | 1 | +| number | 2424 | 2424 | 2424 | 2424 | 1 | +| setNumber | 23784 | 23784 | 23784 | 23784 | 1 | | test/Counter.t.sol:CounterTest Contract | | | | | | |-----------------------------------------|-----------------|--------|--------|--------|---------| | Deployment Cost | Deployment Size | | | | | -| 1544498 | 7573 | | | | | +| 1544498 | 7573 | | | | | | | | | | | | | Function Name | Min | Avg | Median | Max | # Calls | -| setUp | 218902 | 218902 | 218902 | 218902 | 1 | -| test_Increment | 51847 | 51847 | 51847 | 51847 | 1 | +| setUp | 218902 | 218902 | 218902 | 218902 | 1 | +| test_Increment | 51847 | 51847 | 51847 | 51847 | 1 | Ran 1 test suite [ELAPSED]: 1 tests passed, 0 failed, 0 skipped (1 total tests) diff --git a/crates/forge/tests/cli/script.rs b/crates/forge/tests/cli/script.rs index 14217dfaba4de..4a1243051dd88 100644 --- a/crates/forge/tests/cli/script.rs +++ b/crates/forge/tests/cli/script.rs @@ -1945,7 +1945,7 @@ contract SimpleScript is Script { ]) .assert_success() .stdout_eq(str![[r#" -{"logs":[],"returns":{"success":{"internal_type":"bool","value":"true"}},"success":true,"raw_logs":[],"traces":[["Deployment",{"arena":[{"parent":null,"children":[],"idx":0,"trace":{"depth":0,"success":true,"caller":"0x1804c8ab1f12e6bbf3894d4083f33e07309d1f38","address":"0x5b73c5498c1e3b4dba84de0f1833c4a029d90519","maybe_precompile":false,"selfdestruct_address":null,"selfdestruct_refund_target":null,"selfdestruct_transferred_value":null,"kind":"CREATE","value":"0x0","data":"[..]","output":"[..]","gas_used":"{...}","gas_limit":"{...}","status":"Return","steps":[],"decoded":{"label":"SimpleScript","return_data":null,"call_data":null}},"logs":[],"ordering":[]}]}],["Execution",{"arena":[{"parent":null,"children":[1,2],"idx":0,"trace":{"depth":0,"success":true,"caller":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","address":"0x5b73c5498c1e3b4dba84de0f1833c4a029d90519","maybe_precompile":null,"selfdestruct_address":null,"selfdestruct_refund_target":null,"selfdestruct_transferred_value":null,"kind":"CALL","value":"0x0","data":"0xc0406226","output":"0x0000000000000000000000000000000000000000000000000000000000000001","gas_used":"{...}","gas_limit":1073720760,"status":"Return","steps":[],"decoded":{"label":"SimpleScript","return_data":"true","call_data":{"signature":"run()","args":[]}}},"logs":[],"ordering":[{"Call":0},{"Call":1}]},{"parent":0,"children":[],"idx":1,"trace":{"depth":1,"success":true,"caller":"0x5b73c5498c1e3b4dba84de0f1833c4a029d90519","address":"0x7109709ecfa91a80626ff3989d68f67f5b1dd12d","maybe_precompile":null,"selfdestruct_address":null,"selfdestruct_refund_target":null,"selfdestruct_transferred_value":null,"kind":"CALL","value":"0x0","data":"0x7fb5297f","output":"0x","gas_used":"{...}","gas_limit":1056940999,"status":"Return","steps":[],"decoded":{"label":"VM","return_data":null,"call_data":{"signature":"startBroadcast()","args":[]}}},"logs":[],"ordering":[]},{"parent":0,"children":[],"idx":2,"trace":{"depth":1,"success":true,"caller":"0x5b73c5498c1e3b4dba84de0f1833c4a029d90519","address":"0x0000000000000000000000000000000000000000","maybe_precompile":null,"selfdestruct_address":null,"selfdestruct_refund_target":null,"selfdestruct_transferred_value":null,"kind":"CALL","value":"0x0","data":"0x","output":"0x","gas_used":"{...}","gas_limit":1056940650,"status":"Stop","steps":[],"decoded":{"label":null,"return_data":null,"call_data":null}},"logs":[],"ordering":[]}]}]],"gas_used":"{...}","labeled_addresses":{},"returned":"0x0000000000000000000000000000000000000000000000000000000000000001","address":null} +{"logs":[],"returns":{"success":{"internal_type":"bool","value":"true"}},"success":true,"raw_logs":[],"traces":[["Deployment",{"arena":[{"parent":null,"children":[],"idx":0,"trace":{"depth":0,"success":true,"caller":"0x1804c8ab1f12e6bbf3894d4083f33e07309d1f38","address":"0x5b73c5498c1e3b4dba84de0f1833c4a029d90519","maybe_precompile":false,"selfdestruct_address":null,"selfdestruct_refund_target":null,"selfdestruct_transferred_value":null,"kind":"CREATE","value":"0x0","data":"[..]","output":"[..]","gas_used":"{...}","gas_limit":"{...}","gas_refund_counter":0,"status":"Return","steps":[],"decoded":{"label":"SimpleScript","return_data":null,"call_data":null}},"logs":[],"ordering":[]}]}],["Execution",{"arena":[{"parent":null,"children":[1,2],"idx":0,"trace":{"depth":0,"success":true,"caller":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","address":"0x5b73c5498c1e3b4dba84de0f1833c4a029d90519","maybe_precompile":null,"selfdestruct_address":null,"selfdestruct_refund_target":null,"selfdestruct_transferred_value":null,"kind":"CALL","value":"0x0","data":"0xc0406226","output":"0x0000000000000000000000000000000000000000000000000000000000000001","gas_used":"{...}","gas_limit":1073720760,"gas_refund_counter":0,"status":"Return","steps":[],"decoded":{"label":"SimpleScript","return_data":"true","call_data":{"signature":"run()","args":[]}}},"logs":[],"ordering":[{"Call":0},{"Call":1}]},{"parent":0,"children":[],"idx":1,"trace":{"depth":1,"success":true,"caller":"0x5b73c5498c1e3b4dba84de0f1833c4a029d90519","address":"0x7109709ecfa91a80626ff3989d68f67f5b1dd12d","maybe_precompile":null,"selfdestruct_address":null,"selfdestruct_refund_target":null,"selfdestruct_transferred_value":null,"kind":"CALL","value":"0x0","data":"0x7fb5297f","output":"0x","gas_used":"{...}","gas_limit":1056940999,"gas_refund_counter":0,"status":"Return","steps":[],"decoded":{"label":"VM","return_data":null,"call_data":{"signature":"startBroadcast()","args":[]}}},"logs":[],"ordering":[]},{"parent":0,"children":[],"idx":2,"trace":{"depth":1,"success":true,"caller":"0x5b73c5498c1e3b4dba84de0f1833c4a029d90519","address":"0x0000000000000000000000000000000000000000","maybe_precompile":null,"selfdestruct_address":null,"selfdestruct_refund_target":null,"selfdestruct_transferred_value":null,"kind":"CALL","value":"0x0","data":"0x","output":"0x","gas_used":"{...}","gas_limit":1056940650,"gas_refund_counter":0,"status":"Stop","steps":[],"decoded":{"label":null,"return_data":null,"call_data":null}},"logs":[],"ordering":[]}]}]],"gas_used":"{...}","labeled_addresses":{},"returned":"0x0000000000000000000000000000000000000000000000000000000000000001","address":null} {"chain":31337,"estimated_gas_price":"{...}","estimated_total_gas_used":"{...}","estimated_amount_required":"{...}","token_symbol":"ETH"} {"chain":"anvil-hardhat","status":"success","tx_hash":"0x4f78afe915fceb282c7625a68eb350bc0bf78acb59ad893e5c62b710a37f3156","contract_address":null,"block_number":1,"gas_used":"{...}","gas_price":"{...}"} {"status":"success","transactions":"[..]/broadcast/Foo.sol/31337/run-latest.json","sensitive":"[..]/cache/Foo.sol/31337/run-latest.json"} @@ -3144,7 +3144,7 @@ contract CounterScript is Script { Compiler run successful! Traces: [..] → new CounterScript@[..] - └─ ← [Return] 2200 bytes of code + └─ ← [Return] 2162 bytes of code [..] CounterScript::setUp() └─ ← [Stop] diff --git a/crates/forge/tests/cli/test_cmd/fuzz.rs b/crates/forge/tests/cli/test_cmd/fuzz.rs index 7874712a7d21d..fefefb30d9b15 100644 --- a/crates/forge/tests/cli/test_cmd/fuzz.rs +++ b/crates/forge/tests/cli/test_cmd/fuzz.rs @@ -384,6 +384,8 @@ Encountered a total of 1 failing tests, 2 tests succeeded Tip: Run `forge test --rerun` to retry only the 1 failed test +[SEED] (use `--fuzz-seed` to reproduce) + "#]]); }); diff --git a/crates/forge/tests/cli/test_cmd/invariant/common.rs b/crates/forge/tests/cli/test_cmd/invariant/common.rs index 0c765515437a6..eb28ca8c15ca0 100644 --- a/crates/forge/tests/cli/test_cmd/invariant/common.rs +++ b/crates/forge/tests/cli/test_cmd/invariant/common.rs @@ -98,6 +98,8 @@ Encountered a total of 2 failing tests, 1 tests succeeded Tip: Run `forge test --rerun` to retry only the 2 failed tests +[SEED] (use `--fuzz-seed` to reproduce) + "#]]); }); @@ -175,6 +177,8 @@ Encountered a total of 1 failing tests, 0 tests succeeded Tip: Run `forge test --rerun` to retry only the 1 failed test +[SEED] (use `--fuzz-seed` to reproduce) + "#]]); }); @@ -304,6 +308,8 @@ Encountered a total of 1 failing tests, 0 tests succeeded Tip: Run `forge test --rerun` to retry only the 1 failed test +[SEED] (use `--fuzz-seed` to reproduce) + "#]]); }); @@ -373,6 +379,8 @@ Encountered a total of 1 failing tests, 0 tests succeeded Tip: Run `forge test --rerun` to retry only the 1 failed test +[SEED] (use `--fuzz-seed` to reproduce) + "#]]); }); @@ -538,6 +546,8 @@ Encountered a total of 1 failing tests, 0 tests succeeded Tip: Run `forge test --rerun` to retry only the 1 failed test +[SEED] (use `--fuzz-seed` to reproduce) + "#]]); }); @@ -624,6 +634,8 @@ Encountered a total of 1 failing tests, 0 tests succeeded Tip: Run `forge test --rerun` to retry only the 1 failed test +[SEED] (use `--fuzz-seed` to reproduce) + "#]]); }); @@ -696,6 +708,8 @@ Encountered a total of 1 failing tests, 0 tests succeeded Tip: Run `forge test --rerun` to retry only the 1 failed test +[SEED] (use `--fuzz-seed` to reproduce) + "#]]); }); @@ -779,6 +793,8 @@ Encountered a total of 1 failing tests, 0 tests succeeded Tip: Run `forge test --rerun` to retry only the 1 failed test +[SEED] (use `--fuzz-seed` to reproduce) + "#]]); // `fuzz_seed` at 119 makes this sequence shrinkable from 4 to 2. @@ -888,6 +904,8 @@ Encountered a total of 1 failing tests, 0 tests succeeded Tip: Run `forge test --rerun` to retry only the 1 failed test +[SEED] (use `--fuzz-seed` to reproduce) + "#]]); }); @@ -980,6 +998,8 @@ Encountered a total of 1 failing tests, 0 tests succeeded Tip: Run `forge test --rerun` to retry only the 1 failed test +[SEED] (use `--fuzz-seed` to reproduce) + "#]]); }); @@ -1092,6 +1112,8 @@ Encountered a total of 1 failing tests, 0 tests succeeded Tip: Run `forge test --rerun` to retry only the 1 failed test +[SEED] (use `--fuzz-seed` to reproduce) + "#]]); }); @@ -1191,6 +1213,8 @@ Encountered a total of 2 failing tests, 0 tests succeeded Tip: Run `forge test --rerun` to retry only the 2 failed tests +[SEED] (use `--fuzz-seed` to reproduce) + "#]]); }); @@ -1290,6 +1314,8 @@ Encountered a total of 2 failing tests, 0 tests succeeded Tip: Run `forge test --rerun` to retry only the 2 failed tests +[SEED] (use `--fuzz-seed` to reproduce) + "#]]); }); @@ -1589,6 +1615,8 @@ Encountered a total of 2 failing tests, 0 tests succeeded Tip: Run `forge test --rerun` to retry only the 2 failed tests +[SEED] (use `--fuzz-seed` to reproduce) + "#]]); }); diff --git a/crates/forge/tests/cli/test_cmd/invariant/mod.rs b/crates/forge/tests/cli/test_cmd/invariant/mod.rs index db3c8247f175e..3cbeeb4a46db7 100644 --- a/crates/forge/tests/cli/test_cmd/invariant/mod.rs +++ b/crates/forge/tests/cli/test_cmd/invariant/mod.rs @@ -431,6 +431,8 @@ Encountered a total of 1 failing tests, 0 tests succeeded Tip: Run `forge test --rerun` to retry only the 1 failed test +[SEED] (use `--fuzz-seed` to reproduce) + "#]], ); @@ -458,6 +460,8 @@ Encountered a total of 1 failing tests, 0 tests succeeded Tip: Run `forge test --rerun` to retry only the 1 failed test +[SEED] (use `--fuzz-seed` to reproduce) + "#]], ); @@ -481,6 +485,8 @@ Encountered a total of 1 failing tests, 0 tests succeeded Tip: Run `forge test --rerun` to retry only the 1 failed test +[SEED] (use `--fuzz-seed` to reproduce) + "#]], ); }); diff --git a/crates/forge/tests/cli/test_cmd/invariant/target.rs b/crates/forge/tests/cli/test_cmd/invariant/target.rs index 41fadd3cb59d3..a2b766926bb09 100644 --- a/crates/forge/tests/cli/test_cmd/invariant/target.rs +++ b/crates/forge/tests/cli/test_cmd/invariant/target.rs @@ -627,6 +627,8 @@ Encountered a total of 1 failing tests, 0 tests succeeded Tip: Run `forge test --rerun` to retry only the 1 failed test +[SEED] (use `--fuzz-seed` to reproduce) + "#]]); // Test TargetSelectors @@ -670,6 +672,8 @@ Encountered a total of 1 failing tests, 0 tests succeeded Tip: Run `forge test --rerun` to retry only the 1 failed test +[SEED] (use `--fuzz-seed` to reproduce) + "#]], ); @@ -715,6 +719,8 @@ Encountered a total of 1 failing tests, 0 tests succeeded Tip: Run `forge test --rerun` to retry only the 1 failed test +[SEED] (use `--fuzz-seed` to reproduce) + "#]]); // Test TargetArtifactSelectors @@ -763,6 +769,8 @@ Encountered a total of 1 failing tests, 1 tests succeeded Tip: Run `forge test --rerun` to retry only the 1 failed test +[SEED] (use `--fuzz-seed` to reproduce) + "#]]); }); diff --git a/crates/forge/tests/cli/test_cmd/mod.rs b/crates/forge/tests/cli/test_cmd/mod.rs index 1c02fd40e001f..8a2f0e2e7fafe 100644 --- a/crates/forge/tests/cli/test_cmd/mod.rs +++ b/crates/forge/tests/cli/test_cmd/mod.rs @@ -915,6 +915,8 @@ Encountered a total of 1 failing tests, 0 tests succeeded Tip: Run `forge test --rerun` to retry only the 1 failed test +[SEED] (use `--fuzz-seed` to reproduce) + "#]]); }); @@ -966,6 +968,8 @@ Encountered a total of 1 failing tests, 0 tests succeeded Tip: Run `forge test --rerun` to retry only the 1 failed test +[SEED] (use `--fuzz-seed` to reproduce) + "#]]); }); diff --git a/crates/forge/tests/cli/test_cmd/repros.rs b/crates/forge/tests/cli/test_cmd/repros.rs index 2ac4279a7c0e5..82ec6744a6172 100644 --- a/crates/forge/tests/cli/test_cmd/repros.rs +++ b/crates/forge/tests/cli/test_cmd/repros.rs @@ -63,6 +63,8 @@ Encountered a total of 3 failing tests, 0 tests succeeded Tip: Run `forge test --rerun` to retry only the 3 failed tests +[SEED] (use `--fuzz-seed` to reproduce) + "#]]); }); diff --git a/crates/forge/tests/fixtures/SimpleContractTestVerbose.json b/crates/forge/tests/fixtures/SimpleContractTestVerbose.json index eff3ecf321bc8..244a2d94fc7eb 100644 --- a/crates/forge/tests/fixtures/SimpleContractTestVerbose.json +++ b/crates/forge/tests/fixtures/SimpleContractTestVerbose.json @@ -45,6 +45,7 @@ "output": "{...}", "gas_used": "{...}", "gas_limit": "{...}", + "gas_refund_counter": 0, "status": "Return", "steps": [], "decoded": null @@ -78,6 +79,7 @@ "output": "0x", "gas_used": "{...}", "gas_limit": "{...}", + "gas_refund_counter": 0, "status": "Stop", "steps": [ { @@ -10196,6 +10198,7 @@ "output": "{...}", "gas_used": "{...}", "gas_limit": "{...}", + "gas_refund_counter": 0, "status": "Return", "steps": [ { @@ -10564,6 +10567,7 @@ "output": "0x", "gas_used": "{...}", "gas_limit": "{...}", + "gas_refund_counter": 0, "status": "Stop", "steps": [ { @@ -13836,6 +13840,7 @@ "output": "0x", "gas_used": "{...}", "gas_limit": "{...}", + "gas_refund_counter": 0, "status": "Stop", "steps": [], "decoded": null diff --git a/crates/forge/tests/fixtures/invariant_traces.svg b/crates/forge/tests/fixtures/invariant_traces.svg index 37c7bc8ebcf84..8844062c2553c 100644 --- a/crates/forge/tests/fixtures/invariant_traces.svg +++ b/crates/forge/tests/fixtures/invariant_traces.svg @@ -1,4 +1,4 @@ - +