From 7ebb054df138c2737a0509b5542f92e90893615f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20Micha=C5=82ek?= <52135326+cptartur@users.noreply.github.com> Date: Fri, 10 Jan 2025 11:46:57 +0100 Subject: [PATCH 01/13] Run some checks on windows (#2730) Closes #2716 ## Introduced changes - ## Checklist - [ ] Linked relevant issue - [ ] Updated relevant documentation - [ ] Added relevant tests - [ ] Performed self-review of the code - [ ] Added changes to `CHANGELOG.md` --------- Co-authored-by: Franciszek Job <54181625+franciszekjob@users.noreply.github.com> --- .gitattributes | 1 + .github/workflows/ci.yml | 68 ++++++++++++++----- CHANGELOG.md | 7 +- Cargo.lock | 12 +++- Cargo.toml | 1 + crates/forge-runner/Cargo.toml | 1 + crates/forge-runner/src/build_trace_data.rs | 2 +- crates/forge-runner/src/lib.rs | 5 +- .../exit_first/tests/ext_function_test.cairo | 2 +- crates/forge/tests/e2e/build_profile.rs | 10 +-- crates/forge/tests/e2e/build_trace_data.rs | 18 ++--- crates/forge/tests/e2e/io_operations.rs | 22 +++--- crates/forge/tests/e2e/mod.rs | 2 + crates/forge/tests/e2e/running.rs | 26 ++++--- crates/forge/tests/e2e/trace_resources.rs | 2 +- crates/forge/tests/integration/mod.rs | 2 + crates/forge/tests/integration/spy_events.rs | 1 + crates/forge/tests/integration/store_load.rs | 1 + crates/sncast/src/state/state_file.rs | 2 +- crates/sncast/tests/e2e/account/import.rs | 12 +++- crates/sncast/tests/e2e/call.rs | 17 ++++- crates/sncast/tests/e2e/deploy.rs | 15 +++- crates/sncast/tests/e2e/invoke.rs | 15 +++- crates/sncast/tests/e2e/multicall/new.rs | 17 +++-- crates/sncast/tests/e2e/multicall/run.rs | 15 ++-- crates/sncast/tests/e2e/script/init.rs | 2 +- crates/sncast/tests/helpers/devnet.rs | 28 +++++--- crates/sncast/tests/shell/call.ps1 | 19 ++++++ crates/sncast/tests/shell/deploy.ps1 | 14 ++++ crates/sncast/tests/shell/invoke.ps1 | 23 +++++++ scripts/install_devnet.ps1 | 14 ++++ 31 files changed, 296 insertions(+), 80 deletions(-) create mode 100644 .gitattributes create mode 100644 crates/sncast/tests/shell/call.ps1 create mode 100644 crates/sncast/tests/shell/deploy.ps1 create mode 100644 crates/sncast/tests/shell/invoke.ps1 create mode 100644 scripts/install_devnet.ps1 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..7cc205090b --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.* text eol=lf diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6903bcfb45..2c644924a4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,5 +1,8 @@ name: CI +env: + DEVNET_REV: ef789b700770fa27a2fc057b3d1c610771be27d9 + on: pull_request: merge_group: @@ -11,7 +14,10 @@ on: jobs: test-forge-unit-and-integration: name: Test Forge / Unit and Integration Tests - runs-on: ubuntu-latest + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ ubuntu-latest, windows-latest ] steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable @@ -19,11 +25,14 @@ jobs: - uses: software-mansion/setup-scarb@v1 - uses: software-mansion/setup-universal-sierra-compiler@v1 - run: cargo test --release --lib -p forge - - run: cargo test --release --bin snforge - run: cargo test --release integration -p forge build-test-forge-e2e-nextest-archive: - runs-on: ubuntu-latest + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ ubuntu-latest, windows-latest ] steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable @@ -31,48 +40,57 @@ jobs: - name: Install nextest uses: taiki-e/install-action@nextest - name: Build and archive tests - run: cargo nextest archive --release -p forge --archive-file nextest-archive.tar.zst + run: cargo nextest archive --release -p forge --archive-file 'nextest-archive-${{ matrix.os }}.tar.zst' - name: Upload archive to workflow uses: actions/upload-artifact@v4 with: - name: nextest-archive - path: nextest-archive.tar.zst + name: nextest-archive-${{ matrix.os }} + path: nextest-archive-${{ matrix.os }}.tar.zst test-forge-e2e: name: Test Forge / E2E Tests - runs-on: ubuntu-latest + runs-on: ${{ matrix.os }} needs: build-test-forge-e2e-nextest-archive strategy: + fail-fast: false matrix: partition: [ 1, 2, 3, 4, 5, 6, 7, 8 ] + os: [ ubuntu-latest, windows-latest ] steps: - name: Extract branch name if: github.event_name != 'pull_request' run: echo "BRANCH_NAME=$(echo ${GITHUB_REF#refs/heads/})" >> $GITHUB_ENV + shell: bash - name: Extract branch name on pull request if: github.event_name == 'pull_request' run: echo "BRANCH_NAME=$(echo $GITHUB_HEAD_REF)" >> $GITHUB_ENV + shell: bash - name: Extract repo name and owner if: github.event_name != 'pull_request' run: echo "REPO_NAME=$(echo ${{ github.repository }}.git)" >> $GITHUB_ENV + shell: bash - name: Extract repo name and owner on pull request if: github.event_name == 'pull_request' run: echo "REPO_NAME=$(echo ${{ github.event.pull_request.head.repo.full_name }}.git)" >> $GITHUB_ENV + shell: bash - name: Print repo name run: echo 'The repo name is' $REPO_NAME + shell: bash - name: Get branch name run: echo 'The branch name is' $BRANCH_NAME + shell: bash - name: Install cairo-profiler + if: runner.os != 'Windows' run: | curl -L https://raw.githubusercontent.com/software-mansion/cairo-profiler/main/scripts/install.sh | sh - - name: Install cairo-coverage + if: runner.os != 'Windows' run: | curl -L https://raw.githubusercontent.com/software-mansion/cairo-coverage/main/scripts/install.sh | sh @@ -84,9 +102,9 @@ jobs: - uses: taiki-e/install-action@nextest - uses: actions/download-artifact@v4 with: - name: nextest-archive + name: nextest-archive-${{ matrix.os }} - name: nextest partition ${{ matrix.partition }}/8 - run: cargo nextest run --partition 'count:${{ matrix.partition }}/8' --archive-file 'nextest-archive.tar.zst' e2e + run: cargo nextest run --no-fail-fast --partition 'count:${{ matrix.partition }}/8' --archive-file 'nextest-archive-${{ matrix.os }}.tar.zst' e2e test-scarb-2-8-3: name: Test scarb 2.8.3 @@ -188,23 +206,38 @@ jobs: test-cast: name: Test Cast - runs-on: ubuntu-latest + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ ubuntu-latest, windows-latest ] steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@7b1c307e0dcbda6122208f10795a713336a9b35a with: toolchain: stable - uses: Swatinem/rust-cache@82a92a6e8fbeee089604da2575dc567ae9ddeaab - - name: Install starknet-devnet-rs - run: ./scripts/install_devnet.sh + - name: Install starknet-devnet-rs on Linux/Macos + if: runner.os != 'Windows' + run: | + ./scripts/install_devnet.sh + - name: Cache devnet build + if: runner.os == 'Windows' + id: windows-devnet-cache + uses: actions/cache@v4 + with: + path: ${{ github.workspace }}\crates\sncast\tests\utils\devnet + key: ${{ runner.os }}-devnet-${{ env.DEVNET_REV }} + - name: Install devnet + if: runner.os == 'Windows' && steps.windows-devnet-cache.outputs.cache-hit != 'true' + run: | + $DEVNET_INSTALL_DIR = "${{ github.workspace }}\crates\sncast\tests\utils\devnet" + cargo install --git https://github.com/0xSpaceShard/starknet-devnet-rs.git --locked --rev ${{ env.DEVNET_REV }} --root $DEVNET_INSTALL_DIR - uses: software-mansion/setup-scarb@v1 with: scarb-version: "2.7.0" - uses: software-mansion/setup-universal-sierra-compiler@v1 - name: Run tests run: cargo test --release -p sncast - - name: Run test in debug profile - run: cargo test -p sncast test_happy_case_common_arguments_after_subcommand test-conversions: name: Test Conversions @@ -229,7 +262,10 @@ jobs: test-scarb-api: name: Test Scarb Api - runs-on: ubuntu-latest + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ ubuntu-latest, windows-latest ] steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable diff --git a/CHANGELOG.md b/CHANGELOG.md index b613a343c7..87c0f342ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,13 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Forge + +#### Changed + +- Trace files saved in `snfoundry_trace` directory will now use `_` as separators instead of `::` + ### Cast #### Added - interactive interface that allows setting created or imported account as the default - ## [0.35.1] - 2024-12-16 ### Forge diff --git a/Cargo.lock b/Cargo.lock index 459bfe7ef1..041d984469 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -2227,6 +2227,7 @@ dependencies = [ "rand", "rayon", "runtime", + "sanitize-filename", "scarb-api", "semver", "serde", @@ -4423,6 +4424,15 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "sanitize-filename" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc984f4f9ceb736a7bb755c3e3bd17dc56370af2600c9780dcc48c66453da34d" +dependencies = [ + "regex", +] + [[package]] name = "scarb-api" version = "1.0.0" diff --git a/Cargo.toml b/Cargo.toml index 32d2cf3367..24851799cd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -111,3 +111,4 @@ wiremock = "0.6.0" const-hex = "1.14.0" indicatif = "0.17.9" shell-words = "1.1.0" +sanitize-filename = "0.6.0" diff --git a/crates/forge-runner/Cargo.toml b/crates/forge-runner/Cargo.toml index 1abab5362f..ae0dfec1c1 100644 --- a/crates/forge-runner/Cargo.toml +++ b/crates/forge-runner/Cargo.toml @@ -45,3 +45,4 @@ shared = { path = "../shared" } universal-sierra-compiler-api = { path = "../universal-sierra-compiler-api" } fs4.workspace = true which.workspace = true +sanitize-filename.workspace = true diff --git a/crates/forge-runner/src/build_trace_data.rs b/crates/forge-runner/src/build_trace_data.rs index fd9db15d9e..d5ce8019ba 100644 --- a/crates/forge-runner/src/build_trace_data.rs +++ b/crates/forge-runner/src/build_trace_data.rs @@ -292,7 +292,7 @@ fn build_profiler_trace_entry(value: &RelocatedTraceEntry) -> ProfilerTraceEntry } pub fn save_trace_data( - test_name: &String, + test_name: &str, trace_data: &VersionedProfilerCallTrace, ) -> Result { let serialized_trace = diff --git a/crates/forge-runner/src/lib.rs b/crates/forge-runner/src/lib.rs index cd65c6544c..93fee082b5 100644 --- a/crates/forge-runner/src/lib.rs +++ b/crates/forge-runner/src/lib.rs @@ -65,9 +65,10 @@ pub fn maybe_save_trace_and_profile( }) = result { if execution_data_to_save.is_vm_trace_needed() { - let trace_path = save_trace_data(name, trace_data)?; + let name = sanitize_filename::sanitize(name.replace("::", "_")); + let trace_path = save_trace_data(&name, trace_data)?; if execution_data_to_save.profile { - run_profiler(name, &trace_path, &execution_data_to_save.additional_args)?; + run_profiler(&name, &trace_path, &execution_data_to_save.additional_args)?; } return Ok(Some(trace_path)); } diff --git a/crates/forge/tests/data/exit_first/tests/ext_function_test.cairo b/crates/forge/tests/data/exit_first/tests/ext_function_test.cairo index 09d8dc6c93..e74e9adb88 100644 --- a/crates/forge/tests/data/exit_first/tests/ext_function_test.cairo +++ b/crates/forge/tests/data/exit_first/tests/ext_function_test.cairo @@ -2,7 +2,7 @@ use exit_first::fib; #[test] fn hard_test() { - fib(0, 1, 30344); + fib(0, 1, 99999999999999999999999); assert(2 == 2, 'simple check'); } diff --git a/crates/forge/tests/e2e/build_profile.rs b/crates/forge/tests/e2e/build_profile.rs index 975c8e452e..6b3fc59974 100644 --- a/crates/forge/tests/e2e/build_profile.rs +++ b/crates/forge/tests/e2e/build_profile.rs @@ -2,6 +2,7 @@ use super::common::runner::{setup_package, test_runner}; use forge_runner::profiler_api::PROFILE_DIR; #[test] +#[cfg(not(target_os = "windows"))] fn simple_package_build_profile() { let temp = setup_package("simple_package"); @@ -9,19 +10,19 @@ fn simple_package_build_profile() { assert!(temp .join(PROFILE_DIR) - .join("simple_package::tests::test_fib.pb.gz") + .join("simple_package_tests_test_fib.pb.gz") .is_file()); assert!(!temp .join(PROFILE_DIR) - .join("simple_package_integrationtest::test_simple::test_failing.pb.gz") + .join("simple_package_integrationtest_test_simple_test_failing.pb.gz") .is_file()); assert!(!temp .join(PROFILE_DIR) - .join("simple_package::tests::ignored_test.pb.gz") + .join("simple_package_tests_ignored_test.pb.gz") .is_file()); assert!(temp .join(PROFILE_DIR) - .join("simple_package_integrationtest::ext_function_test::test_simple.pb.gz") + .join("simple_package_integrationtest_ext_function_test_test_simple.pb.gz") .is_file()); // Check if it doesn't crash in case some data already exists @@ -29,6 +30,7 @@ fn simple_package_build_profile() { } #[test] +#[cfg(not(target_os = "windows"))] fn simple_package_build_profile_and_pass_args() { let temp = setup_package("simple_package"); diff --git a/crates/forge/tests/e2e/build_trace_data.rs b/crates/forge/tests/e2e/build_trace_data.rs index b8f4f22c45..a794309a9f 100644 --- a/crates/forge/tests/e2e/build_trace_data.rs +++ b/crates/forge/tests/e2e/build_trace_data.rs @@ -16,24 +16,24 @@ fn simple_package_save_trace() { assert!(temp .join(TRACE_DIR) - .join("simple_package::tests::test_fib.json") + .join("simple_package_tests_test_fib.json") .exists()); assert!(!temp .join(TRACE_DIR) - .join("simple_package_integrationtest::test_simple::test_failing.json") + .join("simple_package_integrationtest_test_simple_test_failing.json") .exists()); assert!(!temp .join(TRACE_DIR) - .join("simple_package::tests::ignored_test.json") + .join("simple_package_tests_ignored_test.json") .exists()); assert!(temp .join(TRACE_DIR) - .join("simple_package_integrationtest::ext_function_test::test_simple.json") + .join("simple_package_integrationtest_ext_function_test_test_simple.json") .exists()); let trace_data = fs::read_to_string( temp.join(TRACE_DIR) - .join("simple_package_integrationtest::ext_function_test::test_simple.json"), + .join("simple_package_integrationtest_ext_function_test_test_simple.json"), ) .unwrap(); @@ -56,7 +56,7 @@ fn trace_has_contract_and_function_names() { let trace_data = fs::read_to_string( temp.join(TRACE_DIR) - .join("trace_info_integrationtest::test_trace::test_trace.json"), + .join("trace_info_integrationtest_test_trace_test_trace.json"), ) .unwrap(); @@ -103,7 +103,7 @@ fn trace_has_cairo_execution_info() { let trace_data = fs::read_to_string( temp.join(TRACE_DIR) - .join("trace_info_integrationtest::test_trace::test_trace.json"), + .join("trace_info_integrationtest_test_trace_test_trace.json"), ) .unwrap(); @@ -145,7 +145,7 @@ fn trace_has_deploy_with_no_constructor_phantom_nodes() { let trace_data = fs::read_to_string( temp.join(TRACE_DIR) - .join("trace_info_integrationtest::test_trace::test_trace.json"), + .join("trace_info_integrationtest_test_trace_test_trace.json"), ) .unwrap(); @@ -177,7 +177,7 @@ fn trace_is_produced_even_if_contract_panics() { let trace_data = fs::read_to_string( temp.join(TRACE_DIR) - .join("backtrace_panic::Test::test_contract_panics.json"), + .join("backtrace_panic_Test_test_contract_panics.json"), ) .unwrap(); diff --git a/crates/forge/tests/e2e/io_operations.rs b/crates/forge/tests/e2e/io_operations.rs index af7394c16e..f5731d8e7e 100644 --- a/crates/forge/tests/e2e/io_operations.rs +++ b/crates/forge/tests/e2e/io_operations.rs @@ -1,6 +1,6 @@ use super::common::runner::{setup_package_with_file_patterns, test_runner, BASE_FILE_PATTERNS}; use assert_fs::fixture::PathChild; -use indoc::indoc; +use indoc::formatdoc; use shared::test_utils::output_assert::assert_stdout_contains; #[test] @@ -11,7 +11,13 @@ fn file_reading() { &[BASE_FILE_PATTERNS, &["**/*.txt", "**/*.json"]].concat(), ); - let expected = indoc! {r#" + let expected_file_error = if cfg!(target_os = "windows") { + "The system cannot find the file specified[..]" + } else { + "No such file or directory [..]" + }; + + let expected = formatdoc! {r#" [..]Compiling[..] [..]Finished[..] @@ -21,7 +27,7 @@ fn file_reading() { [FAIL] file_reading_integrationtest::test::json_non_existent Failure data: - "No such file or directory [..]" + "{}" [FAIL] file_reading_integrationtest::test::invalid_json @@ -31,7 +37,7 @@ fn file_reading() { [FAIL] file_reading_integrationtest::test::non_existent Failure data: - "No such file or directory [..]" + "{}" [FAIL] file_reading_integrationtest::test::non_ascii @@ -62,24 +68,24 @@ fn file_reading() { file_reading_integrationtest::test::non_ascii file_reading_integrationtest::test::valid_content_different_folder file_reading_integrationtest::test::negative_number - "#}; + "#, expected_file_error, expected_file_error}; // run from different directories to make sure cwd is always set to package directory let output = test_runner(&temp).assert().code(1); - assert_stdout_contains(output, expected); + assert_stdout_contains(output, &expected); let output = test_runner(&temp) .current_dir(temp.child("src")) .assert() .code(1); - assert_stdout_contains(output, expected); + assert_stdout_contains(output, &expected); let output = test_runner(&temp) .current_dir(temp.child("data")) .assert() .code(1); - assert_stdout_contains(output, expected); + assert_stdout_contains(output, &expected); } diff --git a/crates/forge/tests/e2e/mod.rs b/crates/forge/tests/e2e/mod.rs index 838700d5bd..27b4da0141 100644 --- a/crates/forge/tests/e2e/mod.rs +++ b/crates/forge/tests/e2e/mod.rs @@ -11,7 +11,9 @@ mod coverage; mod docs_snippets_validation; mod env; mod features; +#[cfg(not(target_os = "windows"))] mod fork_warning; +#[cfg(not(target_os = "windows"))] mod forking; mod fuzzing; mod io_operations; diff --git a/crates/forge/tests/e2e/running.rs b/crates/forge/tests/e2e/running.rs index 0b18c2553d..d547747a75 100644 --- a/crates/forge/tests/e2e/running.rs +++ b/crates/forge/tests/e2e/running.rs @@ -1100,21 +1100,31 @@ fn detailed_resources_flag() { fn catch_runtime_errors() { let temp = setup_package("simple_package"); + let expected_panic = if cfg!(target_os = "windows") { + "The system cannot find the file specified" + } else { + "No such file or directory" + }; + temp.child("tests/test.cairo") - .write_str(indoc!( - r#" - use snforge_std::fs::{FileTrait, read_txt}; + .write_str( + formatdoc!( + r#" + use snforge_std::fs::{{FileTrait, read_txt}}; #[test] - #[should_panic(expected: "No such file or directory (os error 2)")] - fn catch_no_such_file() { + #[should_panic(expected: "{}")] + fn catch_no_such_file() {{ let file = FileTrait::new("no_way_this_file_exists"); let content = read_txt(@file); assert!(false); - } - "# - )) + }} + "#, + expected_panic + ) + .as_str(), + ) .unwrap(); let output = test_runner(&temp).assert(); diff --git a/crates/forge/tests/e2e/trace_resources.rs b/crates/forge/tests/e2e/trace_resources.rs index 7ceb37373f..8d2b69651a 100644 --- a/crates/forge/tests/e2e/trace_resources.rs +++ b/crates/forge/tests/e2e/trace_resources.rs @@ -65,7 +65,7 @@ fn assert_resources_for_test( fn deserialize_call_trace(test_name: &str, temp_dir: &TempDir) -> VersionedProfilerCallTrace { let trace_data = fs::read_to_string(temp_dir.join(TRACE_DIR).join(format!( - "trace_resources_tests::{test_name}::{test_name}.json" + "trace_resources_tests_{test_name}_{test_name}.json" ))) .unwrap(); serde_json::from_str(&trace_data).expect("Failed to parse call trace") diff --git a/crates/forge/tests/integration/mod.rs b/crates/forge/tests/integration/mod.rs index 50358ba7a3..6332e29e26 100644 --- a/crates/forge/tests/integration/mod.rs +++ b/crates/forge/tests/integration/mod.rs @@ -3,6 +3,7 @@ mod cheat_block_number; mod cheat_block_timestamp; mod cheat_caller_address; mod cheat_execution_info; +#[cfg(not(target_os = "windows"))] mod cheat_fork; mod cheat_sequencer_address; mod declare; @@ -23,6 +24,7 @@ mod pure_cairo; mod replace_bytecode; mod resources; mod runtime; +#[cfg(not(target_os = "windows"))] mod setup_fork; mod should_panic; mod signing; diff --git a/crates/forge/tests/integration/spy_events.rs b/crates/forge/tests/integration/spy_events.rs index 7e3d08385e..a1014c12a0 100644 --- a/crates/forge/tests/integration/spy_events.rs +++ b/crates/forge/tests/integration/spy_events.rs @@ -631,6 +631,7 @@ fn assert_not_emitted_fails() { assert_case_output_contains(&result, "assert_not_emitted_fails", "keys was emitted"); } +#[cfg(not(target_os = "windows"))] #[test] fn capture_cairo0_event() { let test = test_case!( diff --git a/crates/forge/tests/integration/store_load.rs b/crates/forge/tests/integration/store_load.rs index aebe21fdcf..3e8e52834c 100644 --- a/crates/forge/tests/integration/store_load.rs +++ b/crates/forge/tests/integration/store_load.rs @@ -556,6 +556,7 @@ fn store_load_felt_to_felt() { assert_passed(&result); } +#[cfg(not(target_os = "windows"))] #[test] fn fork_store_load() { let test = test_utils::test_case!(formatdoc!( diff --git a/crates/sncast/src/state/state_file.rs b/crates/sncast/src/state/state_file.rs index 920ea6f93c..bd0258d666 100644 --- a/crates/sncast/src/state/state_file.rs +++ b/crates/sncast/src/state/state_file.rs @@ -396,7 +396,7 @@ mod tests { } #[test] - #[should_panic(expected = "No such file or directory (os error 2)")] + #[should_panic(expected = "Failed to load state file")] fn test_load_state_file_invalid_path() { let state_file = Utf8PathBuf::from("bla/bla/crypto.json"); load_state_file(&state_file).unwrap(); diff --git a/crates/sncast/tests/e2e/account/import.rs b/crates/sncast/tests/e2e/account/import.rs index bbc3328f67..f67c7afb86 100644 --- a/crates/sncast/tests/e2e/account/import.rs +++ b/crates/sncast/tests/e2e/account/import.rs @@ -451,12 +451,18 @@ pub async fn test_invalid_private_key_file_path() { let snapbox = runner(&args); let output = snapbox.assert().success(); + let expected_file_error = if cfg!(target_os = "windows") { + "The system cannot find the file specified[..]" + } else { + "No such file or directory [..]" + }; + assert_stderr_contains( output, - indoc! {r" + formatdoc! {r" command: account import - error: Failed to obtain private key from the file my_private_key: No such file or directory (os error 2) - "}, + error: Failed to obtain private key from the file my_private_key: {} + ", expected_file_error}, ); } diff --git a/crates/sncast/tests/e2e/call.rs b/crates/sncast/tests/e2e/call.rs index 157102e856..6dd3e846ec 100644 --- a/crates/sncast/tests/e2e/call.rs +++ b/crates/sncast/tests/e2e/call.rs @@ -231,10 +231,23 @@ fn test_wrong_block_id() { #[test] fn test_happy_case_shell() { - let test_path = PathBuf::from("tests/shell/call.sh").canonicalize().unwrap(); + let script_extension = if cfg!(windows) { ".ps1" } else { ".sh" }; + let test_path = PathBuf::from(format!("tests/shell/call{script_extension}")) + .canonicalize() + .unwrap(); let binary_path = cargo_bin!("sncast"); - let snapbox = Command::new(test_path) + let command = if cfg!(windows) { + Command::new("powershell") + .arg("-ExecutionPolicy") + .arg("Bypass") + .arg("-File") + .arg(test_path) + } else { + Command::new(test_path) + }; + + let snapbox = command .arg(binary_path) .arg(URL) .arg(DATA_TRANSFORMER_CONTRACT_ADDRESS_SEPOLIA); diff --git a/crates/sncast/tests/e2e/deploy.rs b/crates/sncast/tests/e2e/deploy.rs index feb57b8f0a..3de61512d4 100644 --- a/crates/sncast/tests/e2e/deploy.rs +++ b/crates/sncast/tests/e2e/deploy.rs @@ -440,12 +440,23 @@ fn test_too_low_max_fee() { async fn test_happy_case_shell() { let tempdir = create_and_deploy_oz_account().await; - let test_path = PathBuf::from("tests/shell/deploy.sh") + let script_extension = if cfg!(windows) { ".ps1" } else { ".sh" }; + let test_path = PathBuf::from(format!("tests/shell/deploy{script_extension}")) .canonicalize() .unwrap(); let binary_path = cargo_bin!("sncast"); - let snapbox = Command::new(test_path) + let command = if cfg!(windows) { + Command::new("powershell") + .arg("-ExecutionPolicy") + .arg("Bypass") + .arg("-File") + .arg(test_path) + } else { + Command::new(test_path) + }; + + let snapbox = command .current_dir(tempdir.path()) .arg(binary_path) .arg(URL) diff --git a/crates/sncast/tests/e2e/invoke.rs b/crates/sncast/tests/e2e/invoke.rs index 4d7fa721f2..63c85afba3 100644 --- a/crates/sncast/tests/e2e/invoke.rs +++ b/crates/sncast/tests/e2e/invoke.rs @@ -429,12 +429,23 @@ async fn test_happy_case_cairo_expression_calldata() { async fn test_happy_case_shell() { let tempdir = create_and_deploy_oz_account().await; - let test_path = PathBuf::from("tests/shell/invoke.sh") + let script_extension = if cfg!(windows) { ".ps1" } else { ".sh" }; + let test_path = PathBuf::from(format!("tests/shell/invoke{script_extension}")) .canonicalize() .unwrap(); let binary_path = cargo_bin!("sncast"); - let snapbox = Command::new(test_path) + let command = if cfg!(windows) { + Command::new("powershell") + .arg("-ExecutionPolicy") + .arg("Bypass") + .arg("-File") + .arg(test_path) + } else { + Command::new(test_path) + }; + + let snapbox = command .current_dir(tempdir.path()) .arg(binary_path) .arg(URL) diff --git a/crates/sncast/tests/e2e/multicall/new.rs b/crates/sncast/tests/e2e/multicall/new.rs index 79a8703ebc..0e813c085e 100644 --- a/crates/sncast/tests/e2e/multicall/new.rs +++ b/crates/sncast/tests/e2e/multicall/new.rs @@ -1,6 +1,6 @@ use crate::helpers::constants::ACCOUNT_FILE_PATH; use crate::helpers::runner::runner; -use indoc::indoc; +use indoc::{formatdoc, indoc}; use shared::test_utils::output_assert::{assert_stderr_contains, assert_stdout_contains, AsOutput}; use sncast::helpers::constants::DEFAULT_MULTICALL_CONTENTS; use tempfile::tempdir; @@ -47,7 +47,7 @@ async fn test_no_output_path_specified() { error: the following required arguments were not provided: - Usage: sncast multicall new + Usage: sncast[..] multicall new For more information, try '--help'. "}; @@ -73,12 +73,19 @@ async fn test_directory_non_existent() { let output = snapbox.assert().success(); assert!(output.as_stdout().is_empty()); + + let expected_file_error = if cfg!(target_os = "windows") { + "The system cannot find the path specified[..]" + } else { + "No such file or directory [..]" + }; + assert_stderr_contains( output, - indoc! {r" + formatdoc! {r" command: multicall new - error: No such file or directory[..] - "}, + error: {} + ", expected_file_error}, ); } diff --git a/crates/sncast/tests/e2e/multicall/run.rs b/crates/sncast/tests/e2e/multicall/run.rs index b944555c6f..557bed9c2f 100644 --- a/crates/sncast/tests/e2e/multicall/run.rs +++ b/crates/sncast/tests/e2e/multicall/run.rs @@ -1,7 +1,7 @@ use crate::helpers::constants::{ACCOUNT_FILE_PATH, MULTICALL_CONFIGS_DIR, URL}; use crate::helpers::fixtures::create_and_deploy_oz_account; use crate::helpers::runner::runner; -use indoc::indoc; +use indoc::{formatdoc, indoc}; use shared::test_utils::output_assert::{assert_stderr_contains, AsOutput}; use std::path::Path; use test_case::test_case; @@ -112,12 +112,19 @@ async fn test_invalid_path() { let output = snapbox.assert().success(); assert!(output.as_stdout().is_empty()); + + let expected_file_error = if cfg!(target_os = "windows") { + "The system cannot find the file specified[..]" + } else { + "No such file or directory [..]" + }; + assert_stderr_contains( output, - indoc! {r" + formatdoc! {r" command: multicall run - error: No such file or directory [..] - "}, + error: {} + ", expected_file_error}, ); } diff --git a/crates/sncast/tests/e2e/script/init.rs b/crates/sncast/tests/e2e/script/init.rs index 669ce5ea8f..5dcfe5c73c 100644 --- a/crates/sncast/tests/e2e/script/init.rs +++ b/crates/sncast/tests/e2e/script/init.rs @@ -133,7 +133,7 @@ fn test_initialized_script_compiles() { formatdoc! {r" [WARNING] The newly created script isn't auto-added to the workspace. [..] command: script init - message: Successfully initialized `{script_name}` at [..]/scripts/{script_name} + message: Successfully initialized `{script_name}` at [..]{script_name} "}, ); diff --git a/crates/sncast/tests/helpers/devnet.rs b/crates/sncast/tests/helpers/devnet.rs index 491f0634fb..63ebc92281 100644 --- a/crates/sncast/tests/helpers/devnet.rs +++ b/crates/sncast/tests/helpers/devnet.rs @@ -34,7 +34,13 @@ fn start_devnet() { } } - Command::new("tests/utils/devnet/starknet-devnet") + let devnet_path = if cfg!(target_os = "windows") { + "tests/utils/devnet/bin/starknet-devnet.exe" + } else { + "tests/utils/devnet/starknet-devnet" + }; + + Command::new(devnet_path) .args([ "--port", &port, @@ -81,11 +87,17 @@ fn start_devnet() { #[dtor] fn stop_devnet() { let port = Url::parse(URL).unwrap().port().unwrap_or(80).to_string(); - Command::new("pkill") - .args([ - "-f", - &format!("starknet-devnet.*{}.*{}", &port, &SEED.to_string())[..], - ]) - .spawn() - .expect("Failed to kill devnet processes"); + let pattern = format!("starknet-devnet.*{port}.*{SEED}"); + + if cfg!(target_os = "windows") { + Command::new("taskkill") + .args(["/IM", &pattern, "/F"]) + .output() + .expect("Failed to kill devnet processes"); + } else { + Command::new("pkill") + .args(["-f", &pattern]) + .output() + .expect("Failed to kill devnet processes"); + } } diff --git a/crates/sncast/tests/shell/call.ps1 b/crates/sncast/tests/shell/call.ps1 new file mode 100644 index 0000000000..12bcf8fbc3 --- /dev/null +++ b/crates/sncast/tests/shell/call.ps1 @@ -0,0 +1,19 @@ +$CAST_BINARY = $args[0] +$URL = $args[1] +$DATA_TRANSFORMER_CONTRACT_ADDRESS_SEPOLIA = $args[2] +& $CAST_BINARY ` + --int-format ` + --json ` + call ` + --url $URL ` + --contract-address $DATA_TRANSFORMER_CONTRACT_ADDRESS_SEPOLIA ` + --function complex_fn ` + --arguments @' +array![array![1, 2], array![3, 4, 5], array![6]], +12, +-128_i8, +\"Some string (a ByteArray)\", +('a shortstring', 32_u32), +true, +0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +'@ diff --git a/crates/sncast/tests/shell/deploy.ps1 b/crates/sncast/tests/shell/deploy.ps1 new file mode 100644 index 0000000000..40f369bad8 --- /dev/null +++ b/crates/sncast/tests/shell/deploy.ps1 @@ -0,0 +1,14 @@ +$CAST_BINARY = $args[0] +$URL = $args[1] +$CONSTRUCTOR_WITH_PARAMS_CONTRACT_CLASS_HASH_SEPOLIA = $args[2] +& $CAST_BINARY ` + --accounts-file accounts.json ` + --account my_account ` + --int-format ` + --json ` + deploy ` + --url $URL ` + --class-hash $CONSTRUCTOR_WITH_PARAMS_CONTRACT_CLASS_HASH_SEPOLIA ` + --arguments '0x420, 0x2137_u256' ` + --max-fee 99999999999999999 ` + --fee-token eth diff --git a/crates/sncast/tests/shell/invoke.ps1 b/crates/sncast/tests/shell/invoke.ps1 new file mode 100644 index 0000000000..e9eeb02f07 --- /dev/null +++ b/crates/sncast/tests/shell/invoke.ps1 @@ -0,0 +1,23 @@ +$CAST_BINARY = $args[0] +$URL = $args[1] +$DATA_TRANSFORMER_CONTRACT_ADDRESS_SEPOLIA = $args[2] +& $CAST_BINARY ` + --accounts-file accounts.json ` + --account my_account ` + --int-format ` + --json ` + invoke ` + --url $URL ` + --contract-address $DATA_TRANSFORMER_CONTRACT_ADDRESS_SEPOLIA ` + --function complex_fn ` + --arguments @' +array![array![1, 2], array![3, 4, 5], array![6]], +12, +-128_i8, +\"Some string (a ByteArray)\", +('a shortstring', 32_u32), +true, +0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff +'@ ` + --max-fee 99999999999999999 ` + --fee-token eth diff --git a/scripts/install_devnet.ps1 b/scripts/install_devnet.ps1 new file mode 100644 index 0000000000..f73ea76f62 --- /dev/null +++ b/scripts/install_devnet.ps1 @@ -0,0 +1,14 @@ +Set-StrictMode -Version Latest + +$ErrorActionPreference = "Stop" + +$DEVNET_INSTALL_DIR = Join-Path (git rev-parse --show-toplevel) "crates\sncast\tests\utils\devnet" + +$DEVNET_REPO = "https://github.com/0xSpaceShard/starknet-devnet-rs.git" +$DEVNET_REV = "ef789b700770fa27a2fc057b3d1c610771be27d9" + +cargo install --locked --git $DEVNET_REPO --rev $DEVNET_REV --root $DEVNET_INSTALL_DIR --force + +Write-Host "All done!" + +exit 0 From ec1fee9f4e9bd35d9b84b3c42aa4834e85d3dc7c Mon Sep 17 00:00:00 2001 From: ksew1 <95349104+ksew1@users.noreply.github.com> Date: Mon, 13 Jan 2025 17:19:38 +0100 Subject: [PATCH 02/13] Refactor spinner (#2846) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Stack**: - #2847 - #2846 ⬅ ⚠️ *Part of a stack created by [spr](https://github.com/ejoffe/spr). Do not merge manually using the UI - doing so may have unexpected results.* --- Cargo.lock | 1 + crates/shared/Cargo.toml | 1 + crates/shared/src/lib.rs | 1 + crates/shared/src/spinner.rs | 25 +++++++++++++ .../universal-sierra-compiler-api/src/lib.rs | 36 +++++++++---------- .../src/spinner.rs | 11 ++---- 6 files changed, 49 insertions(+), 26 deletions(-) create mode 100644 crates/shared/src/spinner.rs diff --git a/Cargo.lock b/Cargo.lock index 041d984469..0ac28a6f3f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4768,6 +4768,7 @@ dependencies = [ "anyhow", "cairo-lang-runner", "console", + "indicatif", "regex", "semver", "snapbox", diff --git a/crates/shared/Cargo.toml b/crates/shared/Cargo.toml index 02370a8e3f..2ed5e1a797 100644 --- a/crates/shared/Cargo.toml +++ b/crates/shared/Cargo.toml @@ -13,3 +13,4 @@ starknet.workspace = true url.workspace = true regex.workspace = true snapbox.workspace = true +indicatif.workspace = true diff --git a/crates/shared/src/lib.rs b/crates/shared/src/lib.rs index 348e3da3a0..a806e62024 100644 --- a/crates/shared/src/lib.rs +++ b/crates/shared/src/lib.rs @@ -10,6 +10,7 @@ pub mod command; pub mod consts; pub mod print; pub mod rpc; +pub mod spinner; pub mod test_utils; pub mod utils; diff --git a/crates/shared/src/spinner.rs b/crates/shared/src/spinner.rs new file mode 100644 index 0000000000..a6b9d7326f --- /dev/null +++ b/crates/shared/src/spinner.rs @@ -0,0 +1,25 @@ +use indicatif::{ProgressBar, ProgressStyle}; +use std::borrow::Cow; +use std::time::Duration; + +/// Styled spinner that uses [`ProgressBar`]. +/// Automatically finishes and clears itself when dropped. +pub struct Spinner(ProgressBar); +impl Spinner { + /// Create [`Spinner`] with a message. + pub fn create_with_message(message: impl Into>) -> Self { + let spinner = ProgressBar::new_spinner(); + let style = ProgressStyle::with_template("\n{spinner} {msg}\n") + .expect("template is static str and should be valid"); + spinner.set_style(style); + spinner.enable_steady_tick(Duration::from_millis(100)); + spinner.set_message(message); + Self(spinner) + } +} + +impl Drop for Spinner { + fn drop(&mut self) { + self.0.finish_and_clear(); + } +} diff --git a/crates/universal-sierra-compiler-api/src/lib.rs b/crates/universal-sierra-compiler-api/src/lib.rs index 2efc16c690..95f6dac51d 100644 --- a/crates/universal-sierra-compiler-api/src/lib.rs +++ b/crates/universal-sierra-compiler-api/src/lib.rs @@ -9,7 +9,7 @@ use std::io::Write; use std::str::from_utf8; use tempfile::Builder; -use crate::spinner::spawn_spinner_message; +use crate::spinner::spawn_usc_spinner; pub use command::*; use shared::command::CommandExt; @@ -72,25 +72,25 @@ pub fn compile_sierra_at_path( sierra_file_path: &Utf8Path, sierra_type: &SierraType, ) -> Result { - let spinner = spawn_spinner_message(sierra_file_path)?; - - let mut usc_command = UniversalSierraCompilerCommand::new(); - let usc_output = usc_command - .inherit_stderr() - .args(vec![ - &("compile-".to_string() + &sierra_type.to_string()), - "--sierra-path", - sierra_file_path.as_str(), - ]) - .command() - .output_checked() - .context( - "Error while compiling Sierra. \ + let usc_output = { + let _spinner = spawn_usc_spinner(sierra_file_path)?; + + let mut usc_command = UniversalSierraCompilerCommand::new(); + usc_command + .inherit_stderr() + .args(vec![ + &("compile-".to_string() + &sierra_type.to_string()), + "--sierra-path", + sierra_file_path.as_str(), + ]) + .command() + .output_checked() + .context( + "Error while compiling Sierra. \ Make sure you have the latest universal-sierra-compiler binary installed. \ Contact us if it doesn't help", - )?; - - spinner.finish_and_clear(); + )? + }; Ok(T::convert(from_utf8(&usc_output.stdout)?.to_string())) } diff --git a/crates/universal-sierra-compiler-api/src/spinner.rs b/crates/universal-sierra-compiler-api/src/spinner.rs index f382b757a4..3137c13ab4 100644 --- a/crates/universal-sierra-compiler-api/src/spinner.rs +++ b/crates/universal-sierra-compiler-api/src/spinner.rs @@ -1,14 +1,9 @@ use anyhow::Result; use camino::Utf8Path; -use indicatif::{ProgressBar, ProgressStyle}; +use shared::spinner::Spinner; use std::env; -use std::time::Duration; - -pub fn spawn_spinner_message(sierra_file_path: &Utf8Path) -> Result { - let spinner = ProgressBar::new_spinner(); - spinner.set_style(ProgressStyle::with_template("\n{spinner} {msg}\n")?); - spinner.enable_steady_tick(Duration::from_millis(100)); +pub fn spawn_usc_spinner(sierra_file_path: &Utf8Path) -> Result { // Skip printing path when compiling unsaved sierra // which occurs during test execution for some cheatcodes e.g. `replace_bytecode` let message = if is_temp_file(sierra_file_path)? { @@ -19,7 +14,7 @@ pub fn spawn_spinner_message(sierra_file_path: &Utf8Path) -> Result sierra_file_path.canonicalize_utf8()? ) }; - spinner.set_message(message); + let spinner = Spinner::create_with_message(message); Ok(spinner) } From 926572594e99a5c34901128e4983637c010c5c3c Mon Sep 17 00:00:00 2001 From: ksew1 <95349104+ksew1@users.noreply.github.com> Date: Mon, 13 Jan 2025 17:53:30 +0100 Subject: [PATCH 03/13] Add spinner for coverage and profiler (#2847) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Stack**: - #2847 ⬅ - #2846 ⚠️ *Part of a stack created by [spr](https://github.com/ejoffe/spr). Do not merge manually using the UI - doing so may have unexpected results.* --- crates/forge-runner/src/lib.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crates/forge-runner/src/lib.rs b/crates/forge-runner/src/lib.rs index 93fee082b5..59eec2bf67 100644 --- a/crates/forge-runner/src/lib.rs +++ b/crates/forge-runner/src/lib.rs @@ -13,6 +13,7 @@ use futures::StreamExt; use package_tests::with_config_resolved::TestCaseWithResolvedConfig; use profiler_api::run_profiler; use shared::print::print_as_warning; +use shared::spinner::Spinner; use std::collections::HashMap; use std::path::PathBuf; use std::sync::Arc; @@ -68,6 +69,7 @@ pub fn maybe_save_trace_and_profile( let name = sanitize_filename::sanitize(name.replace("::", "_")); let trace_path = save_trace_data(&name, trace_data)?; if execution_data_to_save.profile { + let _spinner = Spinner::create_with_message("Running cairo-profiler"); run_profiler(&name, &trace_path, &execution_data_to_save.additional_args)?; } return Ok(Some(trace_path)); @@ -84,6 +86,7 @@ pub fn maybe_generate_coverage( if saved_trace_data_paths.is_empty() { print_as_warning(&anyhow!("No trace data to generate coverage from")); } else { + let _spinner = Spinner::create_with_message("Running cairo-coverage"); run_coverage( saved_trace_data_paths, &execution_data_to_save.additional_args, From f8e0c1edb34724894ae774727ab58d3242c3626a Mon Sep 17 00:00:00 2001 From: kkawula <57270771+kkawula@users.noreply.github.com> Date: Mon, 13 Jan 2025 20:14:04 +0100 Subject: [PATCH 04/13] Update discord link (#2844) Closes # ## Introduced changes - ## Checklist - [x] Linked relevant issue - [x] Updated relevant documentation - [x] Added relevant tests - [x] Performed self-review of the code - [x] Added changes to `CHANGELOG.md` --- crates/forge/src/lib.rs | 2 +- crates/sncast/src/main.rs | 2 +- scripts/snfoundryup | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/forge/src/lib.rs b/crates/forge/src/lib.rs index 93e4cbc8ad..3d8fc7a0dc 100644 --- a/crates/forge/src/lib.rs +++ b/crates/forge/src/lib.rs @@ -56,7 +56,7 @@ Read the docs: Join the community: - Follow core developers on X: https://twitter.com/swmansionxyz - Get support via Telegram: https://t.me/starknet_foundry_support -- Or discord: https://discord.gg/KZWaFtPZJf +- Or discord: https://discord.gg/starknet-community - Or join our general chat (Telegram): https://t.me/starknet_foundry Report bugs: https://github.com/foundry-rs/starknet-foundry/issues/new/choose\ diff --git a/crates/sncast/src/main.rs b/crates/sncast/src/main.rs index 2db1f8e788..bb46ca5af7 100644 --- a/crates/sncast/src/main.rs +++ b/crates/sncast/src/main.rs @@ -63,7 +63,7 @@ Read the docs: Join the community: - Follow core developers on X: https://twitter.com/swmansionxyz - Get support via Telegram: https://t.me/starknet_foundry_support -- Or discord: https://discord.gg/KZWaFtPZJf +- Or discord: https://discord.gg/starknet-community - Or join our general chat (Telegram): https://t.me/starknet_foundry Report bugs: https://github.com/foundry-rs/starknet-foundry/issues/new/choose\ diff --git a/scripts/snfoundryup b/scripts/snfoundryup index a87c8a83e7..9d90cd1523 100755 --- a/scripts/snfoundryup +++ b/scripts/snfoundryup @@ -47,7 +47,7 @@ Read the docs: Join the community: - Follow core developers on X: https://twitter.com/swmansionxyz - Get support via Telegram: https://t.me/starknet_foundry_support -- Or discord: https://discord.gg/KZWaFtPZJf +- Or discord: https://discord.gg/starknet-community - Or join our general chat (Telegram): https://t.me/starknet_foundry Report bugs: https://github.com/foundry-rs/starknet-foundry/issues/new/choose From 763ad5b1b9fc281df92ee1d885efc4107fc630e6 Mon Sep 17 00:00:00 2001 From: kkawula <57270771+kkawula@users.noreply.github.com> Date: Mon, 13 Jan 2025 20:44:29 +0100 Subject: [PATCH 05/13] Remove unused dependencies (#2845) Closes # ## Introduced changes - ## Checklist - [x] Linked relevant issue - [x] Updated relevant documentation - [x] Added relevant tests - [x] Performed self-review of the code - [x] Added changes to `CHANGELOG.md` --- Cargo.lock | 13 ------------- crates/forge-runner/Cargo.toml | 1 - crates/snforge-scarb-plugin/Cargo.toml | 2 -- 3 files changed, 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0ac28a6f3f..9f498da050 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2217,7 +2217,6 @@ dependencies = [ "cheatnet", "console", "conversions", - "fs4", "futures", "indoc", "itertools 0.12.1", @@ -2262,16 +2261,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "fs4" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29f9df8a11882c4e3335eb2d18a0137c505d9ca927470b0cac9c6f0ae07d28f7" -dependencies = [ - "rustix", - "windows-sys 0.48.0", -] - [[package]] name = "fs_extra" version = "1.3.0" @@ -4937,8 +4926,6 @@ dependencies = [ name = "snforge_scarb_plugin" version = "0.35.1" dependencies = [ - "cairo-lang-diagnostics", - "cairo-lang-filesystem", "cairo-lang-macro", "cairo-lang-parser", "cairo-lang-syntax", diff --git a/crates/forge-runner/Cargo.toml b/crates/forge-runner/Cargo.toml index ae0dfec1c1..1af06140d5 100644 --- a/crates/forge-runner/Cargo.toml +++ b/crates/forge-runner/Cargo.toml @@ -43,6 +43,5 @@ conversions = { path = "../conversions" } scarb-api = { path = "../scarb-api" } shared = { path = "../shared" } universal-sierra-compiler-api = { path = "../universal-sierra-compiler-api" } -fs4.workspace = true which.workspace = true sanitize-filename.workspace = true diff --git a/crates/snforge-scarb-plugin/Cargo.toml b/crates/snforge-scarb-plugin/Cargo.toml index 502b2c3118..0667da2e82 100644 --- a/crates/snforge-scarb-plugin/Cargo.toml +++ b/crates/snforge-scarb-plugin/Cargo.toml @@ -13,8 +13,6 @@ cairo-lang-macro.workspace = true cairo-lang-parser.workspace = true cairo-lang-utils.workspace = true cairo-lang-syntax.workspace = true -cairo-lang-diagnostics.workspace = true -cairo-lang-filesystem.workspace = true url.workspace = true indoc.workspace = true smol_str.workspace = true From 82480520e00119df5f05c11b6cfc38e6a8ace209 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20Micha=C5=82ek?= <52135326+cptartur@users.noreply.github.com> Date: Tue, 14 Jan 2025 11:44:11 +0100 Subject: [PATCH 06/13] Update work item template (#2818) Closes #2810 ## Introduced changes - ## Checklist - [ ] Linked relevant issue - [ ] Updated relevant documentation - [ ] Added relevant tests - [ ] Performed self-review of the code - [ ] Added changes to `CHANGELOG.md` --------- Co-authored-by: ddoktorski <45050160+ddoktorski@users.noreply.github.com> --- .github/ISSUE_TEMPLATE/work_item.yml | 32 +++++++++++++++++----------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/work_item.yml b/.github/ISSUE_TEMPLATE/work_item.yml index 5de8d547dd..79d5401ed2 100644 --- a/.github/ISSUE_TEMPLATE/work_item.yml +++ b/.github/ISSUE_TEMPLATE/work_item.yml @@ -1,23 +1,29 @@ name: Work item description: Submit an actionable task body: - - type: dropdown - id: tool-name + - type: textarea + id: current-state attributes: - label: Which components does the task require to be changed? (think hard pls) - multiple: true - options: - - snforge - - sncast - - cairo-profiler - - other (describe below) + label: Current State + description: Describe the current state and outline the problem + placeholder: Currently, the `print_a` cheatcode prints `"a"` to stdout. This is problematic because user might want it to be printed on their actual printer. validations: required: true - - type: textarea - id: description + - type: input + id: objective attributes: - label: Description - description: Describe the issue here. + label: Objective + description: Briefly describe the correct state + placeholder: The `print_a` cheatcode should magically detect if user wants to print to stdout or a printer. validations: required: true + + - type: textarea + id: additional-context + attributes: + label: Additional Context + description: Provide additional context on the desired state. + placeholder: If we can detect any printers in local network it might indicate that user wants to print to it. + validations: + required: false From a530f4565727d3e68d502f46fd8ac92173d1dfd1 Mon Sep 17 00:00:00 2001 From: Franciszek Job <54181625+franciszekjob@users.noreply.github.com> Date: Tue, 14 Jan 2025 14:31:36 +0100 Subject: [PATCH 07/13] Validate max gas is greater than zero for strk fee settings (#2796) Closes #2706 ## Introduced changes Validate if fee args are greater than 0 - Change type of `max_fee`, `max_gas` and `max_gas_unit_price` from `Option` to `Option` ## Checklist - [x] Linked relevant issue - [x] Updated relevant documentation - [x] Added relevant tests - [x] Performed self-review of the code - [x] Added changes to `CHANGELOG.md` --- CHANGELOG.md | 5 + crates/conversions/src/lib.rs | 3 + crates/conversions/src/non_zero_felt.rs | 23 +++ crates/conversions/src/non_zero_u128.rs | 14 ++ crates/conversions/src/non_zero_u64.rs | 14 ++ .../src/serde/deserialize/deserialize_impl.rs | 38 +++-- crates/conversions/tests/e2e/mod.rs | 3 + crates/conversions/tests/e2e/non_zero_felt.rs | 21 +++ crates/conversions/tests/e2e/non_zero_u128.rs | 36 +++++ crates/conversions/tests/e2e/non_zero_u64.rs | 36 +++++ crates/sncast/src/helpers/fee.rs | 144 +++++++++++------- .../src/starknet_commands/account/deploy.rs | 14 +- .../sncast/src/starknet_commands/declare.rs | 16 +- crates/sncast/src/starknet_commands/deploy.rs | 6 +- crates/sncast/src/starknet_commands/invoke.rs | 18 ++- crates/sncast/tests/e2e/invoke.rs | 72 +++++++++ crates/sncast/tests/integration/fee.rs | 76 ++++----- docs/src/appendix/sncast/account/deploy.md | 6 +- docs/src/appendix/sncast/declare.md | 6 +- docs/src/appendix/sncast/deploy.md | 6 +- docs/src/appendix/sncast/invoke.md | 6 +- docs/src/appendix/sncast/multicall/run.md | 6 +- 22 files changed, 433 insertions(+), 136 deletions(-) create mode 100644 crates/conversions/src/non_zero_felt.rs create mode 100644 crates/conversions/src/non_zero_u128.rs create mode 100644 crates/conversions/src/non_zero_u64.rs create mode 100644 crates/conversions/tests/e2e/non_zero_felt.rs create mode 100644 crates/conversions/tests/e2e/non_zero_u128.rs create mode 100644 crates/conversions/tests/e2e/non_zero_u64.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 87c0f342ec..c254d1ff7e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,8 +17,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 #### Added +- When using `--max-fee` with transactions v3, calculated max gas and max gas unit price are automatically validated to ensure they are greater than 0 after conversion - interactive interface that allows setting created or imported account as the default +#### Changed + +- Values passed to the `--max-fee`, `--max-gas`, and `--max-gas-unit-price` flags must be greater than 0 + ## [0.35.1] - 2024-12-16 ### Forge diff --git a/crates/conversions/src/lib.rs b/crates/conversions/src/lib.rs index 71af471e1d..2c625bcf3a 100644 --- a/crates/conversions/src/lib.rs +++ b/crates/conversions/src/lib.rs @@ -6,6 +6,9 @@ pub mod contract_address; pub mod entrypoint_selector; pub mod eth_address; pub mod felt; +pub mod non_zero_felt; +pub mod non_zero_u128; +pub mod non_zero_u64; pub mod nonce; pub mod padded_felt; pub mod primitive; diff --git a/crates/conversions/src/non_zero_felt.rs b/crates/conversions/src/non_zero_felt.rs new file mode 100644 index 0000000000..268c48b209 --- /dev/null +++ b/crates/conversions/src/non_zero_felt.rs @@ -0,0 +1,23 @@ +use crate::FromConv; +use starknet_types_core::felt::{Felt, NonZeroFelt}; +use std::num::{NonZeroU128, NonZeroU64}; + +impl FromConv for NonZeroFelt { + fn from_(value: NonZeroU64) -> Self { + NonZeroFelt::try_from(Felt::from(value.get())).unwrap_or_else(|_| { + unreachable!( + "NonZeroU64 is always greater than 0, so it should be convertible to NonZeroFelt" + ) + }) + } +} + +impl FromConv for NonZeroFelt { + fn from_(value: NonZeroU128) -> Self { + NonZeroFelt::try_from(Felt::from(value.get())).unwrap_or_else(|_| { + unreachable!( + "NonZeroU128 is always greater than 0, so it should be convertible to NonZeroFelt" + ) + }) + } +} diff --git a/crates/conversions/src/non_zero_u128.rs b/crates/conversions/src/non_zero_u128.rs new file mode 100644 index 0000000000..2e65c1d7ab --- /dev/null +++ b/crates/conversions/src/non_zero_u128.rs @@ -0,0 +1,14 @@ +use crate::TryFromConv; +use starknet_types_core::felt::{Felt, NonZeroFelt}; +use std::num::{NonZero, NonZeroU128}; + +impl TryFromConv for NonZeroU128 { + type Error = String; + fn try_from_(value: NonZeroFelt) -> Result { + let value: u128 = Felt::from(value) + .try_into() + .map_err(|_| "felt was too large to fit in u128")?; + Ok(NonZero::new(value) + .unwrap_or_else(|| unreachable!("non zero felt is always greater than 0"))) + } +} diff --git a/crates/conversions/src/non_zero_u64.rs b/crates/conversions/src/non_zero_u64.rs new file mode 100644 index 0000000000..6459cb089d --- /dev/null +++ b/crates/conversions/src/non_zero_u64.rs @@ -0,0 +1,14 @@ +use crate::TryFromConv; +use starknet_types_core::felt::{Felt, NonZeroFelt}; +use std::num::{NonZero, NonZeroU64}; + +impl TryFromConv for NonZeroU64 { + type Error = String; + fn try_from_(value: NonZeroFelt) -> Result { + let value: u64 = Felt::from(value) + .try_into() + .map_err(|_| "felt was too large to fit in u64")?; + Ok(NonZero::new(value) + .unwrap_or_else(|| unreachable!("non zero felt is always greater than 0"))) + } +} diff --git a/crates/conversions/src/serde/deserialize/deserialize_impl.rs b/crates/conversions/src/serde/deserialize/deserialize_impl.rs index fc31ddb067..668521a305 100644 --- a/crates/conversions/src/serde/deserialize/deserialize_impl.rs +++ b/crates/conversions/src/serde/deserialize/deserialize_impl.rs @@ -3,8 +3,8 @@ use crate::{byte_array::ByteArray, IntoConv}; use num_traits::cast::ToPrimitive; use starknet::providers::Url; use starknet_api::core::{ClassHash, ContractAddress, EntryPointSelector, Nonce}; -use starknet_types_core::felt::Felt; -use std::num::NonZeroU32; +use starknet_types_core::felt::{Felt, NonZeroFelt}; +use std::num::NonZero; impl CairoDeserialize for Url { fn deserialize(reader: &mut BufferReader<'_>) -> BufferReadResult { @@ -13,12 +13,6 @@ impl CairoDeserialize for Url { } } -impl CairoDeserialize for NonZeroU32 { - fn deserialize(reader: &mut BufferReader<'_>) -> BufferReadResult { - NonZeroU32::new(reader.read()?).ok_or(BufferReadError::ParseFailed) - } -} - impl CairoDeserialize for Felt { fn deserialize(reader: &mut BufferReader<'_>) -> BufferReadResult { reader.read_felt() @@ -71,6 +65,24 @@ impl CairoDeserialize for bool { } } +impl CairoDeserialize for NonZeroFelt { + fn deserialize(reader: &mut BufferReader<'_>) -> BufferReadResult { + let felt = reader.read::()?; + NonZeroFelt::try_from(felt).map_err(|_| BufferReadError::ParseFailed) + } +} + +macro_rules! impl_deserialize_for_nonzero_num_type { + ($type:ty) => { + impl CairoDeserialize for NonZero<$type> { + fn deserialize(reader: &mut BufferReader<'_>) -> BufferReadResult { + let val = <$type>::deserialize(reader)?; + NonZero::new(val).ok_or(BufferReadError::ParseFailed) + } + } + }; +} + macro_rules! impl_deserialize_for_felt_type { ($type:ty) => { impl CairoDeserialize for $type { @@ -80,15 +92,13 @@ macro_rules! impl_deserialize_for_felt_type { } }; } + macro_rules! impl_deserialize_for_num_type { ($type:ty) => { impl CairoDeserialize for $type { fn deserialize(reader: &mut BufferReader<'_>) -> BufferReadResult { let felt = Felt::deserialize(reader)?; - - felt.to_bigint() - .try_into() - .map_err(|_| BufferReadError::ParseFailed) + felt.try_into().map_err(|_| BufferReadError::ParseFailed) } } }; @@ -99,6 +109,10 @@ impl_deserialize_for_felt_type!(ContractAddress); impl_deserialize_for_felt_type!(Nonce); impl_deserialize_for_felt_type!(EntryPointSelector); +impl_deserialize_for_nonzero_num_type!(u32); +impl_deserialize_for_nonzero_num_type!(u64); +impl_deserialize_for_nonzero_num_type!(u128); + impl_deserialize_for_num_type!(u8); impl_deserialize_for_num_type!(u16); impl_deserialize_for_num_type!(u32); diff --git a/crates/conversions/tests/e2e/mod.rs b/crates/conversions/tests/e2e/mod.rs index a030ba2019..98a2224299 100644 --- a/crates/conversions/tests/e2e/mod.rs +++ b/crates/conversions/tests/e2e/mod.rs @@ -3,6 +3,9 @@ mod contract_address; mod entrypoint_selector; mod felt; mod field_elements; +mod non_zero_felt; +mod non_zero_u128; +mod non_zero_u64; mod nonce; mod padded_felt; mod string; diff --git a/crates/conversions/tests/e2e/non_zero_felt.rs b/crates/conversions/tests/e2e/non_zero_felt.rs new file mode 100644 index 0000000000..758bc86fb7 --- /dev/null +++ b/crates/conversions/tests/e2e/non_zero_felt.rs @@ -0,0 +1,21 @@ +#[cfg(test)] +mod tests_non_zero_felt { + use std::num::{NonZeroU128, NonZeroU64}; + + use conversions::FromConv; + use starknet_types_core::felt::{Felt, NonZeroFelt}; + + #[test] + fn test_happy_case() { + let non_zero_felt = NonZeroFelt::try_from(Felt::from(1_u8)).unwrap(); + + assert_eq!( + non_zero_felt, + NonZeroFelt::from_(NonZeroU64::new(1).unwrap()) + ); + assert_eq!( + non_zero_felt, + NonZeroFelt::from_(NonZeroU128::new(1).unwrap()) + ); + } +} diff --git a/crates/conversions/tests/e2e/non_zero_u128.rs b/crates/conversions/tests/e2e/non_zero_u128.rs new file mode 100644 index 0000000000..b79b3f6b67 --- /dev/null +++ b/crates/conversions/tests/e2e/non_zero_u128.rs @@ -0,0 +1,36 @@ +#[cfg(test)] +mod tests_non_zero_u128 { + use conversions::TryFromConv; + use starknet_types_core::felt::{Felt, NonZeroFelt}; + use std::num::NonZeroU128; + + #[test] + fn test_happy_case() { + let non_zero_u128 = NonZeroU128::new(1).unwrap(); + + assert_eq!( + non_zero_u128, + NonZeroU128::try_from_(NonZeroFelt::try_from(Felt::from(1_u8)).unwrap()).unwrap() + ); + } + + #[test] + fn test_limit() { + let felt = Felt::from_dec_str(&u128::MAX.to_string()).unwrap(); + let non_zero_felt = NonZeroFelt::try_from(felt).unwrap(); + + let result = NonZeroU128::try_from_(non_zero_felt); + assert!(result.is_ok()); + assert_eq!(result.unwrap().get(), u128::MAX); + } + + #[test] + fn test_felt_too_large() { + let large_felt = Felt::TWO.pow(128_u8); + let non_zero_felt = NonZeroFelt::try_from(large_felt).unwrap(); + + let result = NonZeroU128::try_from_(non_zero_felt); + assert!(result.is_err()); + assert_eq!(result.unwrap_err(), "felt was too large to fit in u128"); + } +} diff --git a/crates/conversions/tests/e2e/non_zero_u64.rs b/crates/conversions/tests/e2e/non_zero_u64.rs new file mode 100644 index 0000000000..5a9a141dbd --- /dev/null +++ b/crates/conversions/tests/e2e/non_zero_u64.rs @@ -0,0 +1,36 @@ +#[cfg(test)] +mod tests_non_zero_u64 { + use conversions::TryFromConv; + use starknet_types_core::felt::{Felt, NonZeroFelt}; + use std::num::NonZeroU64; + + #[test] + fn test_happy_case() { + let non_zero_u64 = NonZeroU64::new(1).unwrap(); + + assert_eq!( + non_zero_u64, + NonZeroU64::try_from_(NonZeroFelt::try_from(Felt::from(1_u8)).unwrap()).unwrap() + ); + } + + #[test] + fn test_limit() { + let felt = Felt::from_dec_str(&u64::MAX.to_string()).unwrap(); + let non_zero_felt = NonZeroFelt::try_from(felt).unwrap(); + + let result = NonZeroU64::try_from_(non_zero_felt); + assert!(result.is_ok()); + assert_eq!(result.unwrap().get(), u64::MAX); + } + + #[test] + fn test_felt_too_large() { + let large_felt = Felt::TWO.pow(64_u8); + let non_zero_felt = NonZeroFelt::try_from(large_felt).unwrap(); + + let result = NonZeroU64::try_from_(non_zero_felt); + assert!(result.is_err()); + assert_eq!(result.unwrap_err(), "felt was too large to fit in u64"); + } +} diff --git a/crates/sncast/src/helpers/fee.rs b/crates/sncast/src/helpers/fee.rs index 7492961687..55160ffc06 100644 --- a/crates/sncast/src/helpers/fee.rs +++ b/crates/sncast/src/helpers/fee.rs @@ -1,12 +1,14 @@ -use anyhow::{bail, ensure, Error, Result}; +use anyhow::{bail, ensure, Context, Error, Result}; use clap::{Args, ValueEnum}; -use conversions::serde::deserialize::CairoDeserialize; -use conversions::TryIntoConv; +use conversions::{serde::deserialize::CairoDeserialize, FromConv, TryFromConv}; use shared::print::print_as_warning; use starknet::core::types::BlockId; use starknet::providers::Provider; use starknet_types_core::felt::{Felt, NonZeroFelt}; -use std::str::FromStr; +use std::{ + num::{NonZeroU128, NonZeroU64}, + str::FromStr, +}; #[derive(Args, Debug, Clone)] pub struct FeeArgs { @@ -15,16 +17,16 @@ pub struct FeeArgs { pub fee_token: Option, /// Max fee for the transaction. If not provided, will be automatically estimated. - #[clap(short, long)] - pub max_fee: Option, + #[clap(value_parser = parse_non_zero_felt, short, long)] + pub max_fee: Option, /// Max gas amount. If not provided, will be automatically estimated. (Only for STRK fee payment) - #[clap(long)] - pub max_gas: Option, + #[clap(value_parser = parse_non_zero_felt, long)] + pub max_gas: Option, /// Max gas price in Fri. If not provided, will be automatically estimated. (Only for STRK fee payment) - #[clap(long)] - pub max_gas_unit_price: Option, + #[clap(value_parser = parse_non_zero_felt, long)] + pub max_gas_unit_price: Option, } impl From for FeeArgs { @@ -43,8 +45,8 @@ impl From for FeeArgs { } => Self { fee_token: Some(FeeToken::Strk), max_fee, - max_gas: max_gas.map(Into::into), - max_gas_unit_price: max_gas_unit_price.map(Into::into), + max_gas: max_gas.map(NonZeroFelt::from_), + max_gas_unit_price: max_gas_unit_price.map(NonZeroFelt::from_), }, } } @@ -83,53 +85,73 @@ impl FeeArgs { (Some(_), Some(_), Some(_)) => { bail!("Passing all --max-fee, --max-gas and --max-gas-unit-price is conflicting. Please pass only two of them or less") } - (Some(max_fee), Some(max_gas), None) if max_fee < max_gas => { - bail!("--max-fee should be greater than or equal to --max-gas amount") - } - (Some(max_fee), None, Some(max_gas_unit_price)) - if max_fee < max_gas_unit_price => - { - bail!("--max-fee should be greater than or equal to --max-gas-unit-price") - } (None, _, _) => FeeSettings::Strk { - max_gas: self.max_gas.map(TryIntoConv::try_into_).transpose()?, + max_gas: self + .max_gas + .map(NonZeroU64::try_from_) + .transpose() + .map_err(anyhow::Error::msg)?, max_gas_unit_price: self .max_gas_unit_price - .map(TryIntoConv::try_into_) - .transpose()?, - }, - (Some(max_fee), None, Some(max_gas_unit_price)) => FeeSettings::Strk { - max_gas: Some( - max_fee - .floor_div(&NonZeroFelt::from_felt_unchecked(max_gas_unit_price)) - .try_into_()?, - ), - max_gas_unit_price: Some(max_gas_unit_price.try_into_()?), + .map(NonZeroU128::try_from_) + .transpose() + .map_err(anyhow::Error::msg)?, }, - (Some(max_fee), Some(max_gas), None) => FeeSettings::Strk { - max_gas: Some(max_gas.try_into_()?), - max_gas_unit_price: Some( - max_fee - .floor_div(&NonZeroFelt::from_felt_unchecked(max_gas)) - .try_into_()?, - ), - }, - (Some(max_fee), None, None) => { - let max_gas_unit_price = provider - .get_block_with_tx_hashes(block_id) - .await? - .l1_gas_price() - .price_in_fri; + (Some(max_fee), None, Some(max_gas_unit_price)) => { + if max_fee < max_gas_unit_price { + bail!( + "--max-fee should be greater than or equal to --max-gas-unit-price" + ); + } + + let max_gas = NonZeroFelt::try_from(Felt::from(max_fee).floor_div(&max_gas_unit_price)) + .unwrap_or_else(|_| unreachable!("Calculated max gas must be >= 1 because max_fee >= max_gas_unit_price ensures a positive result")); + FeeSettings::Strk { + max_gas: Some( + NonZeroU64::try_from_(max_gas).map_err(anyhow::Error::msg)?, + ), + max_gas_unit_price: Some( + NonZeroU128::try_from_(max_gas_unit_price) + .map_err(anyhow::Error::msg)?, + ), + } + } + (Some(max_fee), Some(max_gas), None) => { + if max_fee < max_gas { + bail!("--max-fee should be greater than or equal to --max-gas amount"); + } + let max_gas_unit_price = NonZeroFelt::try_from(Felt::from(max_fee).floor_div(&max_gas)) + .unwrap_or_else(|_| unreachable!("Calculated max gas unit price must be >= 1 because max_fee >= max_gas ensures a positive result")); + FeeSettings::Strk { + max_gas: Some( + NonZeroU64::try_from_(max_gas).map_err(anyhow::Error::msg)?, + ), + max_gas_unit_price: Some( + NonZeroU128::try_from_(max_gas_unit_price) + .map_err(anyhow::Error::msg)?, + ), + } + } + (Some(max_fee), None, None) => { + let max_gas_unit_price = NonZeroFelt::try_from( + provider + .get_block_with_tx_hashes(block_id) + .await? + .l1_gas_price() + .price_in_fri, + )?; + // TODO(#2852) + let max_gas = NonZeroFelt::try_from(Felt::from(max_fee) + .floor_div(&max_gas_unit_price)).context("Calculated max-gas from provided --max-fee and the current network gas price is 0. Please increase --max-fee to obtain a positive gas amount")?; FeeSettings::Strk { max_gas: Some( - max_fee - .floor_div(&NonZeroFelt::from_felt_unchecked( - max_gas_unit_price, - )) - .try_into_()?, + NonZeroU64::try_from_(max_gas).map_err(anyhow::Error::msg)?, + ), + max_gas_unit_price: Some( + NonZeroU128::try_from_(max_gas_unit_price) + .map_err(anyhow::Error::msg)?, ), - max_gas_unit_price: Some(max_gas_unit_price.try_into_()?), } } }; @@ -152,23 +174,23 @@ pub enum FeeToken { #[derive(Debug, PartialEq, CairoDeserialize)] pub enum ScriptFeeSettings { Eth { - max_fee: Option, + max_fee: Option, }, Strk { - max_fee: Option, - max_gas: Option, - max_gas_unit_price: Option, + max_fee: Option, + max_gas: Option, + max_gas_unit_price: Option, }, } #[derive(Debug, PartialEq)] pub enum FeeSettings { Eth { - max_fee: Option, + max_fee: Option, }, Strk { - max_gas: Option, - max_gas_unit_price: Option, + max_gas: Option, + max_gas_unit_price: Option, }, } @@ -261,3 +283,9 @@ fn parse_fee_token(s: &str) -> Result { Ok(parsed_token) } + +fn parse_non_zero_felt(s: &str) -> Result { + let felt: Felt = s.parse().map_err(|_| "Failed to parse value")?; + felt.try_into() + .map_err(|_| "Value should be greater than 0".to_string()) +} diff --git a/crates/sncast/src/starknet_commands/account/deploy.rs b/crates/sncast/src/starknet_commands/account/deploy.rs index 335c19194e..e8c8bfed96 100644 --- a/crates/sncast/src/starknet_commands/account/deploy.rs +++ b/crates/sncast/src/starknet_commands/account/deploy.rs @@ -263,7 +263,11 @@ where let result = match fee_settings { FeeSettings::Eth { max_fee } => { let deployment = account_factory.deploy_v1(salt); - let deployment = apply_optional(deployment, max_fee, AccountDeploymentV1::max_fee); + let deployment = apply_optional( + deployment, + max_fee.map(Felt::from), + AccountDeploymentV1::max_fee, + ); deployment.send().await } FeeSettings::Strk { @@ -271,10 +275,14 @@ where max_gas_unit_price, } => { let deployment = account_factory.deploy_v3(salt); - let deployment = apply_optional(deployment, max_gas, AccountDeploymentV3::gas); let deployment = apply_optional( deployment, - max_gas_unit_price, + max_gas.map(std::num::NonZero::get), + AccountDeploymentV3::gas, + ); + let deployment = apply_optional( + deployment, + max_gas_unit_price.map(std::num::NonZero::get), AccountDeploymentV3::gas_price, ); deployment.send().await diff --git a/crates/sncast/src/starknet_commands/declare.rs b/crates/sncast/src/starknet_commands/declare.rs index d25a779d37..1fe283adfb 100644 --- a/crates/sncast/src/starknet_commands/declare.rs +++ b/crates/sncast/src/starknet_commands/declare.rs @@ -105,7 +105,8 @@ pub async fn declare( casm_class_hash, ); - let declaration = apply_optional(declaration, max_fee, DeclarationV2::max_fee); + let declaration = + apply_optional(declaration, max_fee.map(Felt::from), DeclarationV2::max_fee); let declaration = apply_optional(declaration, declare.nonce, DeclarationV2::nonce); declaration.send().await @@ -119,9 +120,16 @@ pub async fn declare( casm_class_hash, ); - let declaration = apply_optional(declaration, max_gas, DeclarationV3::gas); - let declaration = - apply_optional(declaration, max_gas_unit_price, DeclarationV3::gas_price); + let declaration = apply_optional( + declaration, + max_gas.map(std::num::NonZero::get), + DeclarationV3::gas, + ); + let declaration = apply_optional( + declaration, + max_gas_unit_price.map(std::num::NonZero::get), + DeclarationV3::gas_price, + ); let declaration = apply_optional(declaration, declare.nonce, DeclarationV3::nonce); declaration.send().await diff --git a/crates/sncast/src/starknet_commands/deploy.rs b/crates/sncast/src/starknet_commands/deploy.rs index 8b3bcb4e29..fb713c6259 100644 --- a/crates/sncast/src/starknet_commands/deploy.rs +++ b/crates/sncast/src/starknet_commands/deploy.rs @@ -91,7 +91,7 @@ pub async fn deploy( let execution = factory.deploy_v1(calldata.clone(), salt, unique); let execution = match max_fee { None => execution, - Some(max_fee) => execution.max_fee(max_fee), + Some(max_fee) => execution.max_fee(max_fee.into()), }; let execution = match nonce { None => execution, @@ -107,11 +107,11 @@ pub async fn deploy( let execution = match max_gas { None => execution, - Some(max_gas) => execution.gas(max_gas), + Some(max_gas) => execution.gas(max_gas.into()), }; let execution = match max_gas_unit_price { None => execution, - Some(max_gas_unit_price) => execution.gas_price(max_gas_unit_price), + Some(max_gas_unit_price) => execution.gas_price(max_gas_unit_price.into()), }; let execution = match nonce { None => execution, diff --git a/crates/sncast/src/starknet_commands/invoke.rs b/crates/sncast/src/starknet_commands/invoke.rs index 8d481d6cf8..d469cfd2d6 100644 --- a/crates/sncast/src/starknet_commands/invoke.rs +++ b/crates/sncast/src/starknet_commands/invoke.rs @@ -89,7 +89,11 @@ pub async fn execute_calls( FeeSettings::Eth { max_fee } => { let execution_calls = account.execute_v1(calls); - let execution = apply_optional(execution_calls, max_fee, ExecutionV1::max_fee); + let execution = apply_optional( + execution_calls, + max_fee.map(Felt::from), + ExecutionV1::max_fee, + ); let execution = apply_optional(execution, nonce, ExecutionV1::nonce); execution.send().await } @@ -99,8 +103,16 @@ pub async fn execute_calls( } => { let execution_calls = account.execute_v3(calls); - let execution = apply_optional(execution_calls, max_gas, ExecutionV3::gas); - let execution = apply_optional(execution, max_gas_unit_price, ExecutionV3::gas_price); + let execution = apply_optional( + execution_calls, + max_gas.map(std::num::NonZero::get), + ExecutionV3::gas, + ); + let execution = apply_optional( + execution, + max_gas_unit_price.map(std::num::NonZero::get), + ExecutionV3::gas_price, + ); let execution = apply_optional(execution, nonce, ExecutionV3::nonce); execution.send().await } diff --git a/crates/sncast/tests/e2e/invoke.rs b/crates/sncast/tests/e2e/invoke.rs index 63c85afba3..17cb37357b 100644 --- a/crates/sncast/tests/e2e/invoke.rs +++ b/crates/sncast/tests/e2e/invoke.rs @@ -388,6 +388,78 @@ fn test_too_low_max_fee() { ); } +#[test] +fn test_max_gas_equal_to_zero() { + let args = vec![ + "--accounts-file", + ACCOUNT_FILE_PATH, + "--account", + "user11", + "--wait", + "invoke", + "--url", + URL, + "--contract-address", + MAP_CONTRACT_ADDRESS_SEPOLIA, + "--function", + "put", + "--calldata", + "0x1", + "0x2", + "--max-gas", + "0", + "--fee-token", + "strk", + ]; + + let snapbox = runner(&args); + let output = snapbox.assert().code(2); + + assert_stderr_contains( + output, + indoc! {r" + error: invalid value '0' for '--max-gas ': Value should be greater than 0 + "}, + ); +} + +#[test] +fn test_calculated_max_gas_equal_to_zero_when_max_fee_passed() { + let args = vec![ + "--accounts-file", + ACCOUNT_FILE_PATH, + "--account", + "user11", + "--wait", + "invoke", + "--url", + URL, + "--contract-address", + MAP_CONTRACT_ADDRESS_SEPOLIA, + "--function", + "put", + "--calldata", + "0x1", + "0x2", + "--max-fee", + "999999", + "--fee-token", + "strk", + ]; + + let snapbox = runner(&args); + let output = snapbox.assert().success(); + + // TODO(#2852) + assert_stderr_contains( + output, + indoc! {r" + command: invoke + error: Calculated max-gas from provided --max-fee and the current network gas price is 0. Please increase --max-fee to obtain a positive gas amount: Tried to create NonZeroFelt from 0 + "}, + ); +} + #[tokio::test] async fn test_happy_case_cairo_expression_calldata() { let tempdir = create_and_deploy_oz_account().await; diff --git a/crates/sncast/tests/integration/fee.rs b/crates/sncast/tests/integration/fee.rs index 8e94db6825..c6c30d2ed9 100644 --- a/crates/sncast/tests/integration/fee.rs +++ b/crates/sncast/tests/integration/fee.rs @@ -1,3 +1,5 @@ +use std::num::{NonZeroU128, NonZeroU64}; + use crate::helpers::constants::URL; use sncast::helpers::constants::OZ_CLASS_HASH; use sncast::helpers::fee::{FeeArgs, FeeSettings, FeeToken}; @@ -5,6 +7,7 @@ use starknet::accounts::{AccountFactory, OpenZeppelinAccountFactory}; use starknet::providers::jsonrpc::HttpTransport; use starknet::providers::{JsonRpcClient, Provider}; use starknet::signers::{LocalWallet, SigningKey}; +use starknet_types_core::felt::Felt; use url::Url; const MAX_FEE: u64 = 1_000_000_000_000; @@ -26,7 +29,7 @@ async fn test_happy_case_eth() { let args = FeeArgs { fee_token: Some(FeeToken::Eth), - max_fee: Some(100_u32.into()), + max_fee: Some(Felt::from(100_u32).try_into().unwrap()), max_gas: None, max_gas_unit_price: None, }; @@ -39,7 +42,7 @@ async fn test_happy_case_eth() { assert_eq!( settings, FeeSettings::Eth { - max_fee: Some(100_u32.into()) + max_fee: Some(Felt::from(100_u32).try_into().unwrap()) } ); } @@ -50,8 +53,8 @@ async fn test_max_gas_eth() { let args = FeeArgs { fee_token: Some(FeeToken::Eth), - max_fee: Some(100_u32.into()), - max_gas: Some(100_u32.into()), + max_fee: Some(Felt::from(100_u32).try_into().unwrap()), + max_gas: Some(Felt::from(100_u32).try_into().unwrap()), max_gas_unit_price: None, }; @@ -71,9 +74,9 @@ async fn test_max_gas_unit_price_eth() { let args = FeeArgs { fee_token: Some(FeeToken::Eth), - max_fee: Some(100_u32.into()), + max_fee: Some(Felt::from(100).try_into().unwrap()), max_gas: None, - max_gas_unit_price: Some(100_u32.into()), + max_gas_unit_price: Some(Felt::from(100_u32).try_into().unwrap()), }; let error = args @@ -92,9 +95,9 @@ async fn test_all_args() { let args = FeeArgs { fee_token: Some(FeeToken::Strk), - max_fee: Some(100_u32.into()), - max_gas: Some(100_u32.into()), - max_gas_unit_price: Some(100_u32.into()), + max_fee: Some(Felt::from(100_u32).try_into().unwrap()), + max_gas: Some(Felt::from(100_u32).try_into().unwrap()), + max_gas_unit_price: Some(Felt::from(100_u32).try_into().unwrap()), }; let error = args @@ -113,8 +116,8 @@ async fn test_max_fee_less_than_max_gas() { let args = FeeArgs { fee_token: Some(FeeToken::Strk), - max_fee: Some(50_u32.into()), - max_gas: Some(100_u32.into()), + max_fee: Some(Felt::from(50_u32).try_into().unwrap()), + max_gas: Some(Felt::from(100_u32).try_into().unwrap()), max_gas_unit_price: None, }; @@ -134,9 +137,9 @@ async fn test_max_fee_less_than_max_gas_unit_price() { let args = FeeArgs { fee_token: Some(FeeToken::Strk), - max_fee: Some(50_u32.into()), + max_fee: Some(Felt::from(50_u32).try_into().unwrap()), max_gas: None, - max_gas_unit_price: Some(100_u32.into()), + max_gas_unit_price: Some(Felt::from(100).try_into().unwrap()), }; let error = args @@ -154,7 +157,7 @@ async fn test_strk_fee_get_max_fee() { let args = FeeArgs { fee_token: Some(FeeToken::Strk), - max_fee: Some(MAX_FEE.into()), + max_fee: Some(Felt::from(MAX_FEE).try_into().unwrap()), max_gas: None, max_gas_unit_price: None, }; @@ -169,10 +172,9 @@ async fn test_strk_fee_get_max_fee() { max_gas, max_gas_unit_price, } => { - assert_eq!( - u128::from(max_gas.unwrap()) * max_gas_unit_price.unwrap(), - MAX_FEE.into() - ); + let max_gas: u64 = max_gas.unwrap().into(); + let max_gas_unit_price: u128 = max_gas_unit_price.unwrap().into(); + assert_eq!(u128::from(max_gas) * max_gas_unit_price, MAX_FEE.into()); } FeeSettings::Eth { .. } => unreachable!(), } @@ -184,8 +186,8 @@ async fn test_strk_fee_get_max_fee_with_max_gas() { let args = FeeArgs { fee_token: Some(FeeToken::Strk), - max_fee: Some(MAX_FEE.into()), - max_gas: Some(1_000_000_u32.into()), + max_fee: Some(Felt::from(MAX_FEE).try_into().unwrap()), + max_gas: Some(Felt::from(1_000_000_u32).try_into().unwrap()), max_gas_unit_price: None, }; @@ -197,8 +199,8 @@ async fn test_strk_fee_get_max_fee_with_max_gas() { assert_eq!( settings, FeeSettings::Strk { - max_gas: Some(1_000_000), - max_gas_unit_price: Some(u128::from(MAX_FEE / 1_000_000)), + max_gas: Some(NonZeroU64::new(1_000_000).unwrap()), + max_gas_unit_price: Some(NonZeroU128::new((MAX_FEE / 1_000_000).into()).unwrap()), } ); @@ -207,10 +209,9 @@ async fn test_strk_fee_get_max_fee_with_max_gas() { max_gas, max_gas_unit_price, } => { - assert_eq!( - u128::from(max_gas.unwrap()) * max_gas_unit_price.unwrap(), - MAX_FEE.into() - ); + let max_gas: u64 = max_gas.unwrap().into(); + let max_gas_unit_price: u128 = max_gas_unit_price.unwrap().into(); + assert_eq!(u128::from(max_gas) * max_gas_unit_price, MAX_FEE.into()); } FeeSettings::Eth { .. } => unreachable!(), } @@ -223,8 +224,8 @@ async fn test_strk_fee_get_max_gas_and_max_gas_unit_price() { let args = FeeArgs { fee_token: Some(FeeToken::Strk), max_fee: None, - max_gas: Some(1_000_000_u32.into()), - max_gas_unit_price: Some(1_000_u32.into()), + max_gas: Some(Felt::from(1_000_000_u32).try_into().unwrap()), + max_gas_unit_price: Some(Felt::from(1_000_u32).try_into().unwrap()), }; let settings = args @@ -235,8 +236,8 @@ async fn test_strk_fee_get_max_gas_and_max_gas_unit_price() { assert_eq!( settings, FeeSettings::Strk { - max_gas: Some(1_000_000), - max_gas_unit_price: Some(1_000), + max_gas: Some(NonZeroU64::new(1_000_000).unwrap()), + max_gas_unit_price: Some(NonZeroU128::new(1_000).unwrap()), } ); } @@ -247,9 +248,9 @@ async fn test_strk_fee_get_max_fee_with_max_gas_unit_price() { let args = FeeArgs { fee_token: Some(FeeToken::Strk), - max_fee: Some(MAX_FEE.into()), + max_fee: Some(Felt::from(MAX_FEE).try_into().unwrap()), max_gas: None, - max_gas_unit_price: Some(1_000_u32.into()), + max_gas_unit_price: Some(Felt::from(1_000_u32).try_into().unwrap()), }; let settings = args @@ -260,8 +261,8 @@ async fn test_strk_fee_get_max_fee_with_max_gas_unit_price() { assert_eq!( settings, FeeSettings::Strk { - max_gas: Some(MAX_FEE / 1_000), - max_gas_unit_price: Some(1_000), + max_gas: Some(NonZeroU64::new(MAX_FEE / 1_000).unwrap()), + max_gas_unit_price: Some(NonZeroU128::new(1_000).unwrap()), } ); @@ -270,10 +271,9 @@ async fn test_strk_fee_get_max_fee_with_max_gas_unit_price() { max_gas, max_gas_unit_price, } => { - assert_eq!( - u128::from(max_gas.unwrap()) * max_gas_unit_price.unwrap(), - MAX_FEE.into() - ); + let max_gas: u64 = max_gas.unwrap().into(); + let max_gas_unit_price: u128 = max_gas_unit_price.unwrap().into(); + assert_eq!(u128::from(max_gas) * max_gas_unit_price, MAX_FEE.into()); } FeeSettings::Eth { .. } => unreachable!(), } diff --git a/docs/src/appendix/sncast/account/deploy.md b/docs/src/appendix/sncast/account/deploy.md index 0357908ee1..9bea12f7b4 100644 --- a/docs/src/appendix/sncast/account/deploy.md +++ b/docs/src/appendix/sncast/account/deploy.md @@ -16,7 +16,7 @@ Overrides url from `snfoundry.toml`. ## `--max-fee, -m ` Optional. -Maximum fee for the `deploy_account` transaction in Fri or Wei depending on fee token or transaction version. When not used, defaults to auto-estimation. +Maximum fee for the `deploy_account` transaction in Fri or Wei depending on fee token or transaction version. When not used, defaults to auto-estimation. Must be greater than zero. ## `--fee-token ` Optional. When not used, defaults to STRK. @@ -26,12 +26,12 @@ Token used for fee payment. Possible values: ETH, STRK. ## `--max-gas ` Optional. -Maximum gas for the `deploy_account` transaction. When not used, defaults to auto-estimation. (Only for STRK fee payment) +Maximum gas for the `deploy_account` transaction. When not used, defaults to auto-estimation. Must be greater than zero. (Only for STRK fee payment) ## ` --max-gas-unit-price ` Optional. -Maximum gas unit price for the `deploy_account` transaction paid in Fri. When not used, defaults to auto-estimation. (Only for STRK fee payment) +Maximum gas unit price for the `deploy_account` transaction paid in Fri. When not used, defaults to auto-estimation. Must be greater than zero. (Only for STRK fee payment) ## `--version, -v ` Optional. When not used, defaults to v3. diff --git a/docs/src/appendix/sncast/declare.md b/docs/src/appendix/sncast/declare.md index 28247ee49b..7ee362515c 100644 --- a/docs/src/appendix/sncast/declare.md +++ b/docs/src/appendix/sncast/declare.md @@ -20,7 +20,7 @@ Overrides url from `snfoundry.toml`. ## `--max-fee, -m ` Optional. -Maximum fee for the `declare` transaction in Fri or Wei depending on fee token or transaction version. When not used, defaults to auto-estimation. +Maximum fee for the `declare` transaction in Fri or Wei depending on fee token or transaction version. When not used, defaults to auto-estimation. Must be greater than zero. ## `--fee-token ` Optional. When not used, defaults to STRK. @@ -30,12 +30,12 @@ Token used for fee payment. Possible values: ETH, STRK. ## `--max-gas ` Optional. -Maximum gas for the `declare` transaction. When not used, defaults to auto-estimation. (Only for STRK fee payment) +Maximum gas for the `declare` transaction. When not used, defaults to auto-estimation. Must be greater than zero. (Only for STRK fee payment) ## ` --max-gas-unit-price ` Optional. -Maximum gas unit price for the `declare` transaction paid in Fri. When not used, defaults to auto-estimation. (Only for STRK fee payment) +Maximum gas unit price for the `declare` transaction paid in Fri. When not used, defaults to auto-estimation. Must be greater than zero. (Only for STRK fee payment) ## `--version, -v ` Optional. When not used, defaults to v3. diff --git a/docs/src/appendix/sncast/deploy.md b/docs/src/appendix/sncast/deploy.md index f5a611cdb7..f10c16185c 100644 --- a/docs/src/appendix/sncast/deploy.md +++ b/docs/src/appendix/sncast/deploy.md @@ -35,7 +35,7 @@ If passed, the salt will be additionally modified with an account address. ## `--max-fee, -m ` Optional. -Maximum fee for the `deploy` transaction in Fri or Wei depending on fee token or transaction version. When not used, defaults to auto-estimation. +Maximum fee for the `deploy` transaction in Fri or Wei depending on fee token or transaction version. When not used, defaults to auto-estimation. Must be greater than zero. ## `--fee-token ` Optional. When not used, defaults to STRK. @@ -45,12 +45,12 @@ Token used for fee payment. Possible values: ETH, STRK. ## `--max-gas ` Optional. -Maximum gas for the `deploy` transaction. When not used, defaults to auto-estimation. (Only for STRK fee payment) +Maximum gas for the `deploy` transaction. When not used, defaults to auto-estimation. Must be greater than zero. (Only for STRK fee payment) ## ` --max-gas-unit-price ` Optional. -Maximum gas unit price for the `deploy` transaction paid in Fri. When not used, defaults to auto-estimation. (Only for STRK fee payment) +Maximum gas unit price for the `deploy` transaction paid in Fri. When not used, defaults to auto-estimation. Must be greater than zero. (Only for STRK fee payment) ## `--version, -v ` Optional. When not used, defaults to v3. diff --git a/docs/src/appendix/sncast/invoke.md b/docs/src/appendix/sncast/invoke.md index d5922648a3..313dee972d 100644 --- a/docs/src/appendix/sncast/invoke.md +++ b/docs/src/appendix/sncast/invoke.md @@ -31,7 +31,7 @@ Overrides url from `snfoundry.toml`. ## `--max-fee, -m ` Optional. -Maximum fee for the `invoke` transaction in Fri or Wei depending on fee token or transaction version. When not used, defaults to auto-estimation. +Maximum fee for the `invoke` transaction in Fri or Wei depending on fee token or transaction version. When not used, defaults to auto-estimation. Must be greater than zero. ## `--fee-token ` Optional. When not used, defaults to STRK. @@ -41,12 +41,12 @@ Token used for fee payment. Possible values: ETH, STRK. ## `--max-gas ` Optional. -Maximum gas for the `invoke` transaction. When not used, defaults to auto-estimation. (Only for STRK fee payment) +Maximum gas for the `invoke` transaction. When not used, defaults to auto-estimation. Must be greater than zero. (Only for STRK fee payment) ## ` --max-gas-unit-price ` Optional. -Maximum gas unit price for the `invoke` transaction paid in Fri. When not used, defaults to auto-estimation. (Only for STRK fee payment) +Maximum gas unit price for the `invoke` transaction paid in Fri. When not used, defaults to auto-estimation. Must be greater than zero. (Only for STRK fee payment) ## `--version, -v ` Optional. When not used, defaults to v3. diff --git a/docs/src/appendix/sncast/multicall/run.md b/docs/src/appendix/sncast/multicall/run.md index ad481c2833..b2a5ae4809 100644 --- a/docs/src/appendix/sncast/multicall/run.md +++ b/docs/src/appendix/sncast/multicall/run.md @@ -21,7 +21,7 @@ Overrides url from `snfoundry.toml`. ## `--max-fee, -m ` Optional. -Maximum fee for the `invoke` transaction in Fri or Wei depending on fee token or transaction version. When not used, defaults to auto-estimation. +Maximum fee for the `invoke` transaction in Fri or Wei depending on fee token or transaction version. When not used, defaults to auto-estimation. Must be greater than zero. ## `--fee-token ` Optional. When not used, defaults to STRK. @@ -31,12 +31,12 @@ Token used for fee payment. Possible values: ETH, STRK. ## `--max-gas ` Optional. -Maximum gas for the `invoke` transaction. When not used, defaults to auto-estimation. (Only for STRK fee payment) +Maximum gas for the `invoke` transaction. When not used, defaults to auto-estimation. Must be greater than zero. (Only for STRK fee payment) ## ` --max-gas-unit-price ` Optional. -Maximum gas unit price for the `invoke` transaction paid in Fri. When not used, defaults to auto-estimation. (Only for STRK fee payment) +Maximum gas unit price for the `invoke` transaction paid in Fri. When not used, defaults to auto-estimation. Must be greater than zero. (Only for STRK fee payment) ## `--version, -v ` Optional. When not used, defaults to v3. From 9dca1ced08c83502f18d0efed1272b564fba5d6f Mon Sep 17 00:00:00 2001 From: kkawula <57270771+kkawula@users.noreply.github.com> Date: Tue, 14 Jan 2025 15:43:39 +0100 Subject: [PATCH 08/13] Add deprecation info of `version` flag (#2834) Closes #2828 ## Introduced changes - ## Checklist - [x] Linked relevant issue - [x] Updated relevant documentation - [x] Added relevant tests - [x] Performed self-review of the code - [x] Added changes to `CHANGELOG.md` --- CHANGELOG.md | 4 ++ crates/sncast/src/helpers/fee.rs | 3 +- crates/sncast/src/helpers/mod.rs | 1 + crates/sncast/src/helpers/version.rs | 10 +++++ .../src/starknet_commands/account/deploy.rs | 3 +- .../sncast/src/starknet_commands/declare.rs | 3 +- crates/sncast/src/starknet_commands/deploy.rs | 3 +- crates/sncast/src/starknet_commands/invoke.rs | 3 +- .../src/starknet_commands/multicall/run.rs | 3 +- crates/sncast/tests/e2e/account/deploy.rs | 36 +++++++++++++++- crates/sncast/tests/e2e/declare.rs | 37 ++++++++++++++++ crates/sncast/tests/e2e/deploy.rs | 43 +++++++++++++++++++ crates/sncast/tests/e2e/invoke.rs | 33 ++++++++++++++ crates/sncast/tests/e2e/multicall/run.rs | 36 ++++++++++++++++ 14 files changed, 210 insertions(+), 8 deletions(-) create mode 100644 crates/sncast/src/helpers/version.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index c254d1ff7e..669acde2d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Values passed to the `--max-fee`, `--max-gas`, and `--max-gas-unit-price` flags must be greater than 0 +#### Deprecated + +- `--version` flag + ## [0.35.1] - 2024-12-16 ### Forge diff --git a/crates/sncast/src/helpers/fee.rs b/crates/sncast/src/helpers/fee.rs index 55160ffc06..ab0eca29c7 100644 --- a/crates/sncast/src/helpers/fee.rs +++ b/crates/sncast/src/helpers/fee.rs @@ -270,7 +270,8 @@ impl FromStr for FeeToken { } fn parse_fee_token(s: &str) -> Result { - let deprecation_message = "Specifying '--fee-token' flag is deprecated and will be removed in the future. Use '--version' instead"; + let deprecation_message = + "Specifying '--fee-token' flag is deprecated and will be removed in the future."; print_as_warning(&Error::msg(deprecation_message)); let parsed_token: FeeToken = s.parse()?; diff --git a/crates/sncast/src/helpers/mod.rs b/crates/sncast/src/helpers/mod.rs index 4dd3519e36..369c5019f5 100644 --- a/crates/sncast/src/helpers/mod.rs +++ b/crates/sncast/src/helpers/mod.rs @@ -8,3 +8,4 @@ pub mod fee; pub mod interactive; pub mod rpc; pub mod scarb_utils; +pub mod version; diff --git a/crates/sncast/src/helpers/version.rs b/crates/sncast/src/helpers/version.rs new file mode 100644 index 0000000000..954770db49 --- /dev/null +++ b/crates/sncast/src/helpers/version.rs @@ -0,0 +1,10 @@ +use anyhow::Error; +use clap::ValueEnum; +use shared::print::print_as_warning; + +const DEPRECATION_MESSAGE: &str = "The '--version' flag is deprecated and will be removed in the future. Version 3 will become the only type of transaction available."; + +pub fn parse_version(s: &str) -> Result { + print_as_warning(&Error::msg(DEPRECATION_MESSAGE)); + T::from_str(s, true) +} diff --git a/crates/sncast/src/starknet_commands/account/deploy.rs b/crates/sncast/src/starknet_commands/account/deploy.rs index e8c8bfed96..682bcf22b3 100644 --- a/crates/sncast/src/starknet_commands/account/deploy.rs +++ b/crates/sncast/src/starknet_commands/account/deploy.rs @@ -8,6 +8,7 @@ use sncast::helpers::constants::{BRAAVOS_BASE_ACCOUNT_CLASS_HASH, KEYSTORE_PASSW use sncast::helpers::error::token_not_supported_for_deployment; use sncast::helpers::fee::{FeeArgs, FeeSettings, FeeToken, PayableTransaction}; use sncast::helpers::rpc::RpcArgs; +use sncast::helpers::version::parse_version; use sncast::response::structs::InvokeResponse; use sncast::{ apply_optional, chain_id_to_network_name, check_account_file_exists, @@ -38,7 +39,7 @@ pub struct Deploy { pub fee_args: FeeArgs, /// Version of the account deployment (can be inferred from fee token) - #[clap(short, long)] + #[clap(short, long, value_parser = parse_version::)] pub version: Option, #[clap(flatten)] diff --git a/crates/sncast/src/starknet_commands/declare.rs b/crates/sncast/src/starknet_commands/declare.rs index 1fe283adfb..3efbd061a8 100644 --- a/crates/sncast/src/starknet_commands/declare.rs +++ b/crates/sncast/src/starknet_commands/declare.rs @@ -6,6 +6,7 @@ use scarb_api::StarknetContractArtifacts; use sncast::helpers::error::token_not_supported_for_declaration; use sncast::helpers::fee::{FeeArgs, FeeSettings, FeeToken, PayableTransaction}; use sncast::helpers::rpc::RpcArgs; +use sncast::helpers::version::parse_version; use sncast::response::errors::StarknetCommandError; use sncast::response::structs::{ AlreadyDeclaredResponse, DeclareResponse, DeclareTransactionResponse, @@ -44,7 +45,7 @@ pub struct Declare { pub package: Option, /// Version of the declaration (can be inferred from fee token) - #[clap(short, long)] + #[clap(short, long, value_parser = parse_version::)] pub version: Option, #[clap(flatten)] diff --git a/crates/sncast/src/starknet_commands/deploy.rs b/crates/sncast/src/starknet_commands/deploy.rs index fb713c6259..7990d0dfef 100644 --- a/crates/sncast/src/starknet_commands/deploy.rs +++ b/crates/sncast/src/starknet_commands/deploy.rs @@ -4,6 +4,7 @@ use conversions::IntoConv; use sncast::helpers::error::token_not_supported_for_deployment; use sncast::helpers::fee::{FeeArgs, FeeSettings, FeeToken, PayableTransaction}; use sncast::helpers::rpc::RpcArgs; +use sncast::helpers::version::parse_version; use sncast::response::errors::StarknetCommandError; use sncast::response::structs::DeployResponse; use sncast::{extract_or_generate_salt, impl_payable_transaction, udc_uniqueness}; @@ -43,7 +44,7 @@ pub struct Deploy { pub nonce: Option, /// Version of the deployment (can be inferred from fee token) - #[clap(short, long)] + #[clap(short, long, value_parser = parse_version::)] pub version: Option, #[clap(flatten)] diff --git a/crates/sncast/src/starknet_commands/invoke.rs b/crates/sncast/src/starknet_commands/invoke.rs index d469cfd2d6..215967d0e5 100644 --- a/crates/sncast/src/starknet_commands/invoke.rs +++ b/crates/sncast/src/starknet_commands/invoke.rs @@ -5,6 +5,7 @@ use conversions::IntoConv; use sncast::helpers::error::token_not_supported_for_invoke; use sncast::helpers::fee::{FeeArgs, FeeSettings, FeeToken, PayableTransaction}; use sncast::helpers::rpc::RpcArgs; +use sncast::helpers::version::parse_version; use sncast::response::errors::StarknetCommandError; use sncast::response::structs::InvokeResponse; use sncast::{apply_optional, handle_wait_for_tx, impl_payable_transaction, WaitForTx}; @@ -38,7 +39,7 @@ pub struct Invoke { pub nonce: Option, /// Version of invoke (can be inferred from fee token) - #[clap(short, long)] + #[clap(short, long, value_parser = parse_version::)] pub version: Option, #[clap(flatten)] diff --git a/crates/sncast/src/starknet_commands/multicall/run.rs b/crates/sncast/src/starknet_commands/multicall/run.rs index 647ee55bc3..ce313e986a 100644 --- a/crates/sncast/src/starknet_commands/multicall/run.rs +++ b/crates/sncast/src/starknet_commands/multicall/run.rs @@ -8,6 +8,7 @@ use sncast::helpers::constants::UDC_ADDRESS; use sncast::helpers::error::token_not_supported_for_invoke; use sncast::helpers::fee::{FeeArgs, FeeToken, PayableTransaction}; use sncast::helpers::rpc::RpcArgs; +use sncast::helpers::version::parse_version; use sncast::response::errors::handle_starknet_command_error; use sncast::response::structs::InvokeResponse; use sncast::{extract_or_generate_salt, impl_payable_transaction, udc_uniqueness, WaitForTx}; @@ -31,7 +32,7 @@ pub struct Run { pub fee_args: FeeArgs, /// Version of invoke (can be inferred from fee token) - #[clap(short, long)] + #[clap(short, long, value_parser = parse_version::)] pub version: Option, #[clap(flatten)] diff --git a/crates/sncast/tests/e2e/account/deploy.rs b/crates/sncast/tests/e2e/account/deploy.rs index 4ea89bb962..8039265bde 100644 --- a/crates/sncast/tests/e2e/account/deploy.rs +++ b/crates/sncast/tests/e2e/account/deploy.rs @@ -399,7 +399,7 @@ async fn test_fee_token_deprecation_warning_eth() { let snapbox = runner(&args).current_dir(tempdir.path()); snapbox.assert().success().stdout_matches(indoc! {r" - [WARNING] Specifying '--fee-token' flag is deprecated and will be removed in the future. Use '--version' instead + [WARNING] Specifying '--fee-token' flag is deprecated and will be removed in the future. [WARNING] Eth transactions will stop being supported in the future due to 'SNIP-16' Transaction hash: [..] command: account deploy @@ -432,7 +432,39 @@ async fn test_fee_token_deprecation_warning_strk() { let snapbox = runner(&args).current_dir(tempdir.path()); snapbox.assert().success().stdout_matches(indoc! {r" - [WARNING] Specifying '--fee-token' flag is deprecated and will be removed in the future. Use '--version' instead + [WARNING] Specifying '--fee-token' flag is deprecated and will be removed in the future. + Transaction hash: [..] + command: account deploy + transaction_hash: [..] + + To see invocation details, visit: + transaction: [..] + "}); +} + +#[tokio::test] +async fn test_version_deprecation_warning() { + let tempdir = create_account(false, &OZ_CLASS_HASH.into_hex_string(), "oz").await; + let accounts_file = "accounts.json"; + + let args = vec![ + "--accounts-file", + accounts_file, + "--wait", + "account", + "deploy", + "--url", + URL, + "--name", + "my_account", + "--version", + "v3", + ]; + + let snapbox = runner(&args).current_dir(tempdir.path()); + + snapbox.assert().success().stdout_matches(indoc! {r" + [WARNING] The '--version' flag is deprecated and will be removed in the future. Version 3 will become the only type of transaction available. Transaction hash: [..] command: account deploy transaction_hash: [..] diff --git a/crates/sncast/tests/e2e/declare.rs b/crates/sncast/tests/e2e/declare.rs index f423075c82..50ce7f917d 100644 --- a/crates/sncast/tests/e2e/declare.rs +++ b/crates/sncast/tests/e2e/declare.rs @@ -729,3 +729,40 @@ async fn test_no_scarb_profile() { "}, ); } + +#[tokio::test] +async fn test_version_deprecation_warning() { + let contract_path = duplicate_contract_directory_with_salt( + CONTRACTS_DIR.to_string() + "/map", + "put", + "human_readable", + ); + let tempdir = create_and_deploy_oz_account().await; + join_tempdirs(&contract_path, &tempdir); + + let args = vec![ + "--accounts-file", + "accounts.json", + "--account", + "my_account", + "declare", + "--url", + URL, + "--contract-name", + "Map", + "--max-fee", + "99999999999999999", + "--version", + "v3", + ]; + + let snapbox = runner(&args).current_dir(tempdir.path()); + let output = snapbox.assert().success(); + + assert_stdout_contains( + output, + indoc! {r" + [WARNING] The '--version' flag is deprecated and will be removed in the future. Version 3 will become the only type of transaction available. + " }, + ); +} diff --git a/crates/sncast/tests/e2e/deploy.rs b/crates/sncast/tests/e2e/deploy.rs index 3de61512d4..eeb8191f00 100644 --- a/crates/sncast/tests/e2e/deploy.rs +++ b/crates/sncast/tests/e2e/deploy.rs @@ -463,3 +463,46 @@ async fn test_happy_case_shell() { .arg(CONSTRUCTOR_WITH_PARAMS_CONTRACT_CLASS_HASH_SEPOLIA); snapbox.assert().success(); } + +#[tokio::test] +async fn test_version_deprecation_warning() { + let tempdir = create_and_deploy_account(OZ_CLASS_HASH, AccountType::OpenZeppelin).await; + + let args = vec![ + "--accounts-file", + "accounts.json", + "--account", + "my_account", + "deploy", + "--url", + URL, + "--class-hash", + MAP_CONTRACT_CLASS_HASH_SEPOLIA, + "--salt", + "0x2", + "--unique", + "--max-fee", + "99999999999999999", + "--version", + "v3", + ]; + + let snapbox = runner(&args).current_dir(tempdir.path()); + let output = snapbox.assert().success(); + + assert_stdout_contains( + output, + indoc! { + " + [WARNING] The '--version' flag is deprecated and will be removed in the future. Version 3 will become the only type of transaction available. + command: deploy + contract_address: 0x0[..] + transaction_hash: 0x0[..] + + To see deployment details, visit: + contract: [..] + transaction: [..] + " + }, + ); +} diff --git a/crates/sncast/tests/e2e/invoke.rs b/crates/sncast/tests/e2e/invoke.rs index 17cb37357b..2853d99705 100644 --- a/crates/sncast/tests/e2e/invoke.rs +++ b/crates/sncast/tests/e2e/invoke.rs @@ -524,3 +524,36 @@ async fn test_happy_case_shell() { .arg(DATA_TRANSFORMER_CONTRACT_ADDRESS_SEPOLIA); snapbox.assert().success(); } + +#[test] +fn test_version_deprecation_warning() { + let args = vec![ + "--accounts-file", + ACCOUNT_FILE_PATH, + "--account", + "oz", + "invoke", + "--url", + URL, + "--contract-address", + MAP_CONTRACT_ADDRESS_SEPOLIA, + "--function", + "put", + "--calldata", + "0x1 0x2", + "--max-fee", + "99999999999999999", + "--version", + "v3", + ]; + + let snapbox = runner(&args); + let output = snapbox.assert().success(); + + assert_stdout_contains( + output, + indoc! {" + [WARNING] The '--version' flag is deprecated and will be removed in the future. Version 3 will become the only type of transaction available. + "}, + ); +} diff --git a/crates/sncast/tests/e2e/multicall/run.rs b/crates/sncast/tests/e2e/multicall/run.rs index 557bed9c2f..338faa7264 100644 --- a/crates/sncast/tests/e2e/multicall/run.rs +++ b/crates/sncast/tests/e2e/multicall/run.rs @@ -317,3 +317,39 @@ async fn test_numeric_overflow() { "}, ); } + +#[tokio::test] +async fn test_version_deprecation_warning() { + let path = project_root::get_project_root().expect("failed to get project root path"); + let path = Path::new(&path) + .join(MULTICALL_CONFIGS_DIR) + .join("deploy_invoke.toml"); + let path = path.to_str().expect("failed converting path to str"); + + let args = vec![ + "--accounts-file", + ACCOUNT_FILE_PATH, + "--account", + "oz", + "multicall", + "run", + "--url", + URL, + "--path", + path, + "--version", + "v3", + ]; + + let snapbox = runner(&args); + let output = snapbox.assert(); + + output.stdout_matches(indoc! {r" + [WARNING] The '--version' flag is deprecated and will be removed in the future. Version 3 will become the only type of transaction available. + command: multicall run + transaction_hash: 0x0[..] + + To see invocation details, visit: + transaction: [..] + "}); +} From 44563cf0ddb1c278adfca7ada8e74ceb17286857 Mon Sep 17 00:00:00 2001 From: Franciszek Job <54181625+franciszekjob@users.noreply.github.com> Date: Tue, 14 Jan 2025 15:44:22 +0100 Subject: [PATCH 09/13] Print max fee conversion info when using v3 txs (#2797) Closes #2707 ## Introduced changes Display info about about conversion when using `--max-fee` flag with v3 transactions ## Checklist - [x] Linked relevant issue - [x] Updated relevant documentation - [x] Added relevant tests - [x] Performed self-review of the code - [x] Added changes to `CHANGELOG.md` --------- Co-authored-by: Piotr Figiela <77412592+Draggu@users.noreply.github.com> --- crates/sncast/src/helpers/fee.rs | 17 +++++++++++++++++ crates/sncast/tests/e2e/account/deploy.rs | 9 +++++++++ crates/sncast/tests/e2e/invoke.rs | 12 ++++++++++-- 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/crates/sncast/src/helpers/fee.rs b/crates/sncast/src/helpers/fee.rs index ab0eca29c7..9bb983d1eb 100644 --- a/crates/sncast/src/helpers/fee.rs +++ b/crates/sncast/src/helpers/fee.rs @@ -61,6 +61,7 @@ impl FeeArgs { } } + #[allow(clippy::too_many_lines)] pub async fn try_into_fee_settings( &self, provider: P, @@ -106,6 +107,7 @@ impl FeeArgs { let max_gas = NonZeroFelt::try_from(Felt::from(max_fee).floor_div(&max_gas_unit_price)) .unwrap_or_else(|_| unreachable!("Calculated max gas must be >= 1 because max_fee >= max_gas_unit_price ensures a positive result")); + print_max_fee_conversion_info(max_fee, max_gas, max_gas_unit_price); FeeSettings::Strk { max_gas: Some( NonZeroU64::try_from_(max_gas).map_err(anyhow::Error::msg)?, @@ -123,6 +125,7 @@ impl FeeArgs { let max_gas_unit_price = NonZeroFelt::try_from(Felt::from(max_fee).floor_div(&max_gas)) .unwrap_or_else(|_| unreachable!("Calculated max gas unit price must be >= 1 because max_fee >= max_gas ensures a positive result")); + print_max_fee_conversion_info(max_fee, max_gas, max_gas_unit_price); FeeSettings::Strk { max_gas: Some( NonZeroU64::try_from_(max_gas).map_err(anyhow::Error::msg)?, @@ -144,6 +147,7 @@ impl FeeArgs { // TODO(#2852) let max_gas = NonZeroFelt::try_from(Felt::from(max_fee) .floor_div(&max_gas_unit_price)).context("Calculated max-gas from provided --max-fee and the current network gas price is 0. Please increase --max-fee to obtain a positive gas amount")?; + print_max_fee_conversion_info(max_fee, max_gas, max_gas_unit_price); FeeSettings::Strk { max_gas: Some( NonZeroU64::try_from_(max_gas).map_err(anyhow::Error::msg)?, @@ -285,6 +289,19 @@ fn parse_fee_token(s: &str) -> Result { Ok(parsed_token) } +fn print_max_fee_conversion_info( + max_fee: impl Into, + max_gas: impl Into, + max_gas_unit_price: impl Into, +) { + let max_fee: Felt = max_fee.into(); + let max_gas: Felt = max_gas.into(); + let max_gas_unit_price: Felt = max_gas_unit_price.into(); + println!( + "Specifying '--max-fee' flag while using v3 transactions results in conversion to '--max-gas' and '--max-gas-unit-price' flags\nConverted {max_fee} max fee to {max_gas} max gas and {max_gas_unit_price} max gas unit price\n", + ); +} + fn parse_non_zero_felt(s: &str) -> Result { let felt: Felt = s.parse().map_err(|_| "Failed to parse value")?; felt.try_into() diff --git a/crates/sncast/tests/e2e/account/deploy.rs b/crates/sncast/tests/e2e/account/deploy.rs index 8039265bde..de59901dcc 100644 --- a/crates/sncast/tests/e2e/account/deploy.rs +++ b/crates/sncast/tests/e2e/account/deploy.rs @@ -495,6 +495,9 @@ pub async fn test_valid_class_hash() { let snapbox = runner(&args).current_dir(tempdir.path()); snapbox.assert().success().stdout_matches(indoc! {r" + Specifying '--max-fee' flag while using v3 transactions results in conversion to '--max-gas' and '--max-gas-unit-price' flags + Converted [..] max fee to [..] max gas and [..] max gas unit price + command: account deploy transaction_hash: [..] @@ -616,6 +619,9 @@ pub async fn test_happy_case_keystore(account_type: &str) { let snapbox = runner(&args).current_dir(tempdir.path()); snapbox.assert().stdout_matches(indoc! {r" + Specifying '--max-fee' flag while using v3 transactions results in conversion to '--max-gas' and '--max-gas-unit-price' flags + Converted [..] max fee to [..] max gas and [..] max gas unit price + command: account deploy transaction_hash: 0x0[..] @@ -889,6 +895,9 @@ pub async fn test_deploy_keystore_other_args() { let snapbox = runner(&args).current_dir(tempdir.path()); snapbox.assert().stdout_matches(indoc! {r" + Specifying '--max-fee' flag while using v3 transactions results in conversion to '--max-gas' and '--max-gas-unit-price' flags + Converted [..] max fee to [..] max gas and [..] max gas unit price + command: account deploy transaction_hash: 0x0[..] diff --git a/crates/sncast/tests/e2e/invoke.rs b/crates/sncast/tests/e2e/invoke.rs index 2853d99705..c2e64bd55e 100644 --- a/crates/sncast/tests/e2e/invoke.rs +++ b/crates/sncast/tests/e2e/invoke.rs @@ -128,11 +128,19 @@ async fn test_happy_case_strk(class_hash: Felt, account_type: AccountType) { ]; let snapbox = runner(&args).current_dir(tempdir.path()); - let output = snapbox.assert().success().get_output().stdout.clone(); + let output = snapbox.assert().success(); + let stdout = output.get_output().stdout.clone(); - let hash = get_transaction_hash(&output); + let hash = get_transaction_hash(&stdout); let receipt = get_transaction_receipt(hash).await; + assert_stdout_contains( + output, + indoc! { + "Specifying '--max-fee' flag while using v3 transactions results in conversion to '--max-gas' and '--max-gas-unit-price' flags + Converted [..] max fee to [..] max gas and [..] max gas unit price" + }, + ); assert!(matches!(receipt, Invoke(_))); } From 079563e6152f7c83df74f5ffae986ee9bfb2f26f Mon Sep 17 00:00:00 2001 From: kkawula <57270771+kkawula@users.noreply.github.com> Date: Tue, 14 Jan 2025 20:55:12 +0100 Subject: [PATCH 10/13] Fix `.gitattributes` to correctly handle binary files (#2839) Closes # Binary files should be excluded from line-ending normalization. In the current state, git is trying to normalize binary files that do not have eol char (and never had). This causes a newly cloned repo to have all binary files unstaged with warning `CRLF will be replaced by LF the next time Git touches it`. It may cause confusion in the upcoming hackathon. ## Introduced changes - ## Checklist - [x] Linked relevant issue - [x] Updated relevant documentation - [x] Added relevant tests - [x] Performed self-review of the code - [x] Added changes to `CHANGELOG.md` --- .gitattributes | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitattributes b/.gitattributes index 7cc205090b..d58eab2ee3 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,4 @@ *.* text eol=lf +*.png -text +*.jpg -text +*.gif -text From fd18c58c257d16637ea2dacd7a272ce5e0ef8b26 Mon Sep 17 00:00:00 2001 From: kkawula <57270771+kkawula@users.noreply.github.com> Date: Tue, 14 Jan 2025 20:56:36 +0100 Subject: [PATCH 11/13] Disable `Scheduled` workflow on forks (#2838) Closes # ## Introduced changes - ## Checklist - [x] Linked relevant issue - [x] Updated relevant documentation - [x] Added relevant tests - [x] Performed self-review of the code - [x] Added changes to `CHANGELOG.md` --- .github/workflows/scheduled.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/scheduled.yml b/.github/workflows/scheduled.yml index 596c5d7449..68cab6cab8 100644 --- a/.github/workflows/scheduled.yml +++ b/.github/workflows/scheduled.yml @@ -11,6 +11,7 @@ on: jobs: get-scarb-versions: + if: "! github.event.repository.fork" name: Get Scarb versions outputs: versions: ${{ steps.get_versions.outputs.versions }} @@ -30,6 +31,7 @@ jobs: echo "versions=[${scarb_versions[@]}]" >> "$GITHUB_OUTPUT" test-forge-unit-and-integration: + if: "! github.event.repository.fork" runs-on: ubuntu-latest needs: get-scarb-versions strategy: @@ -50,6 +52,7 @@ jobs: - run: cargo test --release -p forge integration test-forge-e2e: + if: "! github.event.repository.fork" runs-on: ubuntu-latest needs: get-scarb-versions strategy: @@ -89,6 +92,7 @@ jobs: - run: cargo test --release -p forge e2e test-cast: + if: "! github.event.repository.fork" runs-on: ubuntu-latest needs: get-scarb-versions strategy: From 6af1722bad3dd98001285e76f43a83d8b38614de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20Micha=C5=82ek?= <52135326+cptartur@users.noreply.github.com> Date: Wed, 15 Jan 2025 12:41:04 +0100 Subject: [PATCH 12/13] Release 0.36.0 (#2854) Closes # ## Introduced changes - ## Checklist - [ ] Linked relevant issue - [ ] Updated relevant documentation - [ ] Added relevant tests - [ ] Performed self-review of the code - [ ] Added changes to `CHANGELOG.md` --- CHANGELOG.md | 2 ++ Cargo.lock | 10 +++++----- Cargo.toml | 2 +- crates/snforge-scarb-plugin/Scarb.toml | 2 +- sncast_std/Scarb.lock | 2 +- sncast_std/Scarb.toml | 2 +- snforge_std/Scarb.lock | 4 ++-- snforge_std/Scarb.toml | 2 +- 8 files changed, 14 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 669acde2d5..1d86a8e188 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.36.0] - 2025-01-15 + ### Forge #### Changed diff --git a/Cargo.lock b/Cargo.lock index 9f498da050..13aff201f8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1896,7 +1896,7 @@ checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" [[package]] name = "docs" -version = "0.35.1" +version = "0.36.0" dependencies = [ "anyhow", "camino", @@ -2149,7 +2149,7 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "forge" -version = "0.35.1" +version = "0.36.0" dependencies = [ "anyhow", "assert_fs", @@ -2199,7 +2199,7 @@ dependencies = [ [[package]] name = "forge_runner" -version = "0.35.1" +version = "0.36.0" dependencies = [ "anyhow", "blockifier", @@ -4866,7 +4866,7 @@ dependencies = [ [[package]] name = "sncast" -version = "0.35.1" +version = "0.36.0" dependencies = [ "anyhow", "async-trait", @@ -4924,7 +4924,7 @@ dependencies = [ [[package]] name = "snforge_scarb_plugin" -version = "0.35.1" +version = "0.36.0" dependencies = [ "cairo-lang-macro", "cairo-lang-parser", diff --git a/Cargo.toml b/Cargo.toml index 24851799cd..48ec65709c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,7 @@ members = [ ] [workspace.package] -version = "0.35.1" +version = "0.36.0" edition = "2021" repository = "https://github.com/foundry-rs/starknet-foundry" license = "MIT" diff --git a/crates/snforge-scarb-plugin/Scarb.toml b/crates/snforge-scarb-plugin/Scarb.toml index 6c92561508..161e76a975 100644 --- a/crates/snforge-scarb-plugin/Scarb.toml +++ b/crates/snforge-scarb-plugin/Scarb.toml @@ -1,6 +1,6 @@ [package] name = "snforge_scarb_plugin" -version = "0.35.1" +version = "0.36.0" edition = "2024_07" [cairo-plugin] diff --git a/sncast_std/Scarb.lock b/sncast_std/Scarb.lock index 152c497386..63d1258262 100644 --- a/sncast_std/Scarb.lock +++ b/sncast_std/Scarb.lock @@ -3,4 +3,4 @@ version = 1 [[package]] name = "sncast_std" -version = "0.35.1" +version = "0.36.0" diff --git a/sncast_std/Scarb.toml b/sncast_std/Scarb.toml index c4ab7404a6..8859464d47 100644 --- a/sncast_std/Scarb.toml +++ b/sncast_std/Scarb.toml @@ -1,6 +1,6 @@ [package] name = "sncast_std" -version = "0.35.1" +version = "0.36.0" edition = "2023_11" description = "Library used for writing deployment scripts in Cairo" homepage = "https://foundry-rs.github.io/starknet-foundry/starknet/script.html" diff --git a/snforge_std/Scarb.lock b/snforge_std/Scarb.lock index 1f03b8c0a3..d895dcf867 100644 --- a/snforge_std/Scarb.lock +++ b/snforge_std/Scarb.lock @@ -3,11 +3,11 @@ version = 1 [[package]] name = "snforge_scarb_plugin" -version = "0.35.1" +version = "0.36.0" [[package]] name = "snforge_std" -version = "0.35.1" +version = "0.36.0" dependencies = [ "snforge_scarb_plugin", ] diff --git a/snforge_std/Scarb.toml b/snforge_std/Scarb.toml index d8a1cf098c..bd1e9d2d7c 100644 --- a/snforge_std/Scarb.toml +++ b/snforge_std/Scarb.toml @@ -1,6 +1,6 @@ [package] name = "snforge_std" -version = "0.35.1" +version = "0.36.0" edition = "2024_07" description = "Cairo testing library" documentation = "https://foundry-rs.github.io/starknet-foundry/appendix/snforge-library.html" From 8ce451e58b1305f7e6769451a18412970157dc1a Mon Sep 17 00:00:00 2001 From: kkawula <57270771+kkawula@users.noreply.github.com> Date: Wed, 15 Jan 2025 18:58:16 +0100 Subject: [PATCH 13/13] Update installation docs (#2840) Closes # ## Introduced changes - ## Checklist - [x] Linked relevant issue - [x] Updated relevant documentation - [x] Added relevant tests - [x] Performed self-review of the code - [x] Added changes to `CHANGELOG.md` --- docs/src/getting-started/installation.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docs/src/getting-started/installation.md b/docs/src/getting-started/installation.md index 92cd7233f6..5e9818face 100644 --- a/docs/src/getting-started/installation.md +++ b/docs/src/getting-started/installation.md @@ -107,6 +107,12 @@ Install Scarb asdf install scarb latest ``` +Set a version globally (in your ~/.tool-versions file): + +```shell +asdf global scarb latest +``` + To verify that Scarb was installed, run ```shell @@ -129,6 +135,12 @@ Install Starknet Foundry asdf install starknet-foundry latest ``` +Set a version globally (in your ~/.tool-versions file): + +```shell +asdf global starknet-foundry latest +``` + To verify that Starknet Foundry was installed, run ```shell