diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index ef9a9a324d..32fe7261de 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -27,6 +27,8 @@ ENV TABLEGEN_170_PREFIX=/usr/lib/llvm-17 # To allow independent workflow of the container, the rust-toolchain is explicitely given. RUN echo "1.80.0" > rust_toolchain_version +# Make sure to sync the nightly version with the scripts in ./scripts +RUN echo "nightly-2024-08-28" > nightly_rust_toolchain_version # Install cargo-binstall RUN curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash @@ -36,8 +38,8 @@ RUN rustup toolchain install $(cat rust_toolchain_version) && \ rustup component add clippy && \ rustup component add rustfmt -RUN rustup toolchain install nightly && \ - rustup component add rustfmt clippy --toolchain nightly +RUN rustup toolchain install $(cat nightly_rust_toolchain_version) && \ + rustup component add rustfmt clippy --toolchain $(cat nightly_rust_toolchain_version) RUN rustup target add x86_64-pc-windows-msvc && \ rustup target add wasm32-unknown-unknown @@ -60,7 +62,7 @@ RUN if [ "$TARGETPLATFORM" = "linux/arm64" ] ; then \ rm -r hurl-4.1.0-x86_64-unknown-linux-gnu && \ rm hurl.tar.gz && \ rustup component add llvm-tools-preview --toolchain $(cat rust_toolchain_version)-x86_64-unknown-linux-gnu && \ - rustup target add x86_64-fortanix-unknown-sgx --toolchain nightly; \ + rustup target add x86_64-fortanix-unknown-sgx --toolchain $(cat nightly_rust_toolchain_version); \ fi ARG DOJO_VERSION=stable diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 4732318858..958b2312f5 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -2,7 +2,7 @@ // https://github.com/microsoft/vscode-dev-containers/tree/v0.245.2/containers/rust { "name": "Rust", - "image": "ghcr.io/dojoengine/dojo-dev:v1.0.0-alpha.8", + "image": "ghcr.io/dojoengine/dojo-dev:e89ac13", "runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml index 5c3032e147..ffeb0dce05 100644 --- a/.github/workflows/bench.yml +++ b/.github/workflows/bench.yml @@ -14,7 +14,7 @@ jobs: bench-katana: runs-on: ubuntu-latest container: - image: ghcr.io/dojoengine/dojo-dev:v1.0.0-alpha.8 + image: ghcr.io/dojoengine/dojo-dev:e89ac13 steps: - uses: actions/checkout@v3 - run: git config --global --add safe.directory "$GITHUB_WORKSPACE" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a74f329b18..6437c520ac 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,7 @@ jobs: needs: ensure-docker runs-on: ubuntu-latest-32-cores container: - image: ghcr.io/dojoengine/dojo-dev:v1.0.0-alpha.8 + image: ghcr.io/dojoengine/dojo-dev:e89ac13 steps: - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v2 @@ -55,7 +55,7 @@ jobs: ensure-wasm: runs-on: ubuntu-latest container: - image: ghcr.io/dojoengine/dojo-dev:v1.0.0-alpha.8 + image: ghcr.io/dojoengine/dojo-dev:e89ac13 steps: - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v2 @@ -120,7 +120,7 @@ jobs: needs: build runs-on: ubuntu-latest container: - image: ghcr.io/dojoengine/dojo-dev:v1.0.0-alpha.8 + image: ghcr.io/dojoengine/dojo-dev:e89ac13 steps: - uses: actions/download-artifact@v4 with: @@ -135,7 +135,7 @@ jobs: needs: build runs-on: ubuntu-latest container: - image: ghcr.io/dojoengine/dojo-dev:v1.0.0-alpha.8 + image: ghcr.io/dojoengine/dojo-dev:e89ac13 steps: - uses: actions/download-artifact@v4 with: @@ -149,7 +149,7 @@ jobs: dojo-world-bindings-check: runs-on: ubuntu-latest container: - image: ghcr.io/dojoengine/dojo-dev:v1.0.0-alpha.8 + image: ghcr.io/dojoengine/dojo-dev:e89ac13 steps: - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v2 @@ -158,7 +158,7 @@ jobs: clippy: runs-on: ubuntu-latest-4-cores container: - image: ghcr.io/dojoengine/dojo-dev:v1.0.0-alpha.8 + image: ghcr.io/dojoengine/dojo-dev:e89ac13 steps: - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v2 @@ -167,7 +167,7 @@ jobs: fmt: runs-on: ubuntu-latest container: - image: ghcr.io/dojoengine/dojo-dev:v1.0.0-alpha.8 + image: ghcr.io/dojoengine/dojo-dev:e89ac13 steps: - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v2 @@ -176,7 +176,7 @@ jobs: docs: runs-on: ubuntu-latest container: - image: ghcr.io/dojoengine/dojo-dev:v1.0.0-alpha.8 + image: ghcr.io/dojoengine/dojo-dev:e89ac13 steps: - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v2 diff --git a/.github/workflows/release-dispatch.yml b/.github/workflows/release-dispatch.yml index 414d884050..7e297c8248 100644 --- a/.github/workflows/release-dispatch.yml +++ b/.github/workflows/release-dispatch.yml @@ -14,7 +14,7 @@ jobs: contents: write runs-on: ubuntu-latest container: - image: ghcr.io/dojoengine/dojo-dev:v1.0.0-alpha.8 + image: ghcr.io/dojoengine/dojo-dev:e89ac13 env: VERSION: "" steps: diff --git a/bin/sozo/src/commands/build.rs b/bin/sozo/src/commands/build.rs index 49be74a057..2bc18af6f0 100644 --- a/bin/sozo/src/commands/build.rs +++ b/bin/sozo/src/commands/build.rs @@ -11,6 +11,7 @@ use scarb_ui::args::{FeaturesSpec, PackagesFilter}; use sozo_ops::statistics::{get_contract_statistics_for_dir, ContractStatistics}; use tracing::trace; +use crate::commands::check_package_dojo_version; use crate::commands::clean::CleanArgs; const BYTECODE_SIZE_LABEL: &str = "Bytecode size [in felts]\n(Sierra, Casm)"; @@ -58,6 +59,10 @@ impl BuildArgs { ws.members().collect() }; + for p in &packages { + check_package_dojo_version(&ws, p)?; + } + let profile_name = ws.current_profile().expect("Scarb profile is expected at this point.").to_string(); diff --git a/bin/sozo/src/commands/call.rs b/bin/sozo/src/commands/call.rs index beb2497809..d24494ce20 100644 --- a/bin/sozo/src/commands/call.rs +++ b/bin/sozo/src/commands/call.rs @@ -3,11 +3,11 @@ use clap::Args; use dojo_world::contracts::naming::ensure_namespace; use dojo_world::metadata::get_default_namespace_from_ws; use scarb::core::Config; -use starknet::core::types::Felt; use tracing::trace; use super::options::starknet::StarknetOptions; use super::options::world::WorldOptions; +use crate::commands::calldata_decoder; use crate::utils; #[derive(Debug, Args)] @@ -22,8 +22,14 @@ pub struct CallArgs { #[arg(short, long)] #[arg(value_delimiter = ',')] #[arg(help = "The calldata to be passed to the entrypoint. Comma separated values e.g., \ - 0x12345,0x69420.")] - pub calldata: Vec, + 0x12345,128,u256:9999999999. Sozo supports some prefixes that you can use to \ + automatically parse some types. The supported prefixes are: + - u256: A 256-bit unsigned integer. + - sstr: A cairo short string. + - str: A cairo string (ByteArray). + - int: A signed integer. + - no prefix: A cairo felt or any type that fit into one felt.")] + pub calldata: Option, #[arg(short, long)] #[arg(help = "The block ID (could be a hash, a number, 'pending' or 'latest')")] @@ -57,11 +63,18 @@ impl CallArgs { .await .unwrap(); + let calldata = if let Some(cd) = self.calldata { + calldata_decoder::decode_calldata(&cd)? + } else { + vec![] + }; + sozo_ops::call::call( + &config.ui(), world_reader, tag_or_address, self.entrypoint, - self.calldata, + calldata, self.block_id, ) .await diff --git a/bin/sozo/src/commands/mod.rs b/bin/sozo/src/commands/mod.rs index 3933e9f70f..bc3418f856 100644 --- a/bin/sozo/src/commands/mod.rs +++ b/bin/sozo/src/commands/mod.rs @@ -2,7 +2,7 @@ use core::fmt; use anyhow::Result; use clap::Subcommand; -use scarb::core::Config; +use scarb::core::{Config, Package, Workspace}; pub(crate) mod account; pub(crate) mod auth; @@ -133,3 +133,47 @@ pub fn run(command: Commands, config: &Config) -> Result<()> { Commands::Completions(args) => args.run(), } } + +/// Checks if the package has a compatible version of dojo-core. +/// In case of a workspace with multiple packages, each package is individually checked +/// and the workspace manifest path is returned in case of virtual workspace. +pub fn check_package_dojo_version(ws: &Workspace<'_>, package: &Package) -> anyhow::Result<()> { + if let Some(dojo_dep) = + package.manifest.summary.dependencies.iter().find(|dep| dep.name.as_str() == "dojo") + { + let dojo_version = env!("CARGO_PKG_VERSION"); + println!("Dojo version: {}", dojo_version); + + let dojo_dep_str = dojo_dep.to_string(); + println!("Dojo dep: {}", dojo_dep_str); + + // Only in case of git dependency with an explicit tag, we check if the tag is the same as + // the current version. + if dojo_dep_str.contains("git+") + && dojo_dep_str.contains("tag=v") + && !dojo_dep_str.contains(dojo_version) + { + if let Ok(cp) = ws.current_package() { + let path = + if cp.id == package.id { package.manifest_path() } else { ws.manifest_path() }; + + anyhow::bail!( + "Found dojo-core version mismatch: expected {}. Please verify your dojo \ + dependency in {}", + dojo_version, + path + ) + } else { + // Virtual workspace. + anyhow::bail!( + "Found dojo-core version mismatch: expected {}. Please verify your dojo \ + dependency in {}", + dojo_version, + ws.manifest_path() + ) + } + } + } + + Ok(()) +} diff --git a/bin/sozo/src/commands/test.rs b/bin/sozo/src/commands/test.rs index 040565b4d3..05a3dc4daa 100644 --- a/bin/sozo/src/commands/test.rs +++ b/bin/sozo/src/commands/test.rs @@ -20,6 +20,8 @@ use scarb::ops::{self, CompileOpts}; use scarb_ui::args::{FeaturesSpec, PackagesFilter}; use tracing::trace; +use super::check_package_dojo_version; + pub(crate) const LOG_TARGET: &str = "sozo::cli::commands::test"; #[derive(Debug, Clone, PartialEq, clap::ValueEnum)] @@ -81,6 +83,10 @@ impl TestArgs { ws.members().collect() }; + for p in &packages { + check_package_dojo_version(&ws, p)?; + } + let resolve = ops::resolve_workspace(&ws)?; let opts = CompileOpts { diff --git a/crates/sozo/ops/src/call.rs b/crates/sozo/ops/src/call.rs index 251cc07819..12bc197ce6 100644 --- a/crates/sozo/ops/src/call.rs +++ b/crates/sozo/ops/src/call.rs @@ -1,12 +1,15 @@ -use anyhow::{Context, Result}; +use anyhow::Result; use dojo_world::contracts::WorldContractReader; +use scarb_ui::Ui; use starknet::core::types::{BlockId, BlockTag, Felt, FunctionCall}; use starknet::core::utils::get_selector_from_name; use starknet::providers::Provider; +use crate::migration::ui::MigrationUi; use crate::utils::{get_contract_address_from_reader, parse_block_id}; pub async fn call( + ui: &Ui, world_reader: WorldContractReader

, tag_or_address: String, entrypoint: String, @@ -20,7 +23,7 @@ pub async fn call( BlockId::Tag(BlockTag::Pending) }; - let output = world_reader + let res = world_reader .provider() .call( FunctionCall { @@ -30,10 +33,23 @@ pub async fn call( }, block_id, ) - .await - .with_context(|| format!("Failed to call {entrypoint}"))?; + .await; - println!("[ {} ]", output.iter().map(|o| format!("0x{:x}", o)).collect::>().join(" ")); + match res { + Ok(output) => { + println!( + "[ {} ]", + output.iter().map(|o| format!("0x{:x}", o)).collect::>().join(" ") + ); + } + Err(e) => { + ui.print_hidden_sub(format!("{:?}", e)); + anyhow::bail!(format!( + "Error calling entrypoint `{}` on address: {:#066x}", + entrypoint, contract_address + )); + } + } Ok(()) } diff --git a/crates/sozo/ops/src/tests/call.rs b/crates/sozo/ops/src/tests/call.rs index addb2b4e96..f477c64814 100644 --- a/crates/sozo/ops/src/tests/call.rs +++ b/crates/sozo/ops/src/tests/call.rs @@ -1,5 +1,6 @@ use dojo_world::contracts::WorldContractReader; use katana_runner::{KatanaRunner, KatanaRunnerConfig}; +use scarb_ui::Ui; use starknet::accounts::SingleOwnerAccount; use starknet::core::types::Felt; use starknet::providers::jsonrpc::HttpTransport; @@ -21,8 +22,11 @@ async fn call_with_bad_address() { let provider = sequencer.provider(); let world_reader = WorldContractReader::new(world.address, provider); + let ui = Ui::new(scarb_ui::Verbosity::Verbose, scarb_ui::OutputFormat::Text); + assert!( call::call( + &ui, world_reader, "0xBadCoffeeBadCode".to_string(), ENTRYPOINT.to_string(), @@ -43,8 +47,11 @@ async fn call_with_bad_name() { let provider = sequencer.provider(); let world_reader = WorldContractReader::new(world.address, provider); + let ui = Ui::new(scarb_ui::Verbosity::Verbose, scarb_ui::OutputFormat::Text); + assert!( call::call( + &ui, world_reader, "BadName".to_string(), ENTRYPOINT.to_string(), @@ -65,8 +72,11 @@ async fn call_with_bad_entrypoint() { let provider = sequencer.provider(); let world_reader = WorldContractReader::new(world.address, provider); + let ui = Ui::new(scarb_ui::Verbosity::Verbose, scarb_ui::OutputFormat::Text); + assert!( call::call( + &ui, world_reader, CONTRACT_TAG.to_string(), "BadEntryPoint".to_string(), @@ -87,8 +97,11 @@ async fn call_with_bad_calldata() { let provider = sequencer.provider(); let world_reader = WorldContractReader::new(world.address, provider); + let ui = Ui::new(scarb_ui::Verbosity::Verbose, scarb_ui::OutputFormat::Text); + assert!( call::call( + &ui, world_reader, CONTRACT_TAG.to_string(), ENTRYPOINT.to_string(), @@ -109,9 +122,17 @@ async fn call_with_contract_name() { let provider = sequencer.provider(); let world_reader = WorldContractReader::new(world.address, provider); - let r = - call::call(world_reader, CONTRACT_TAG.to_string(), ENTRYPOINT.to_string(), vec![], None) - .await; + let ui = Ui::new(scarb_ui::Verbosity::Verbose, scarb_ui::OutputFormat::Text); + + let r = call::call( + &ui, + world_reader, + CONTRACT_TAG.to_string(), + ENTRYPOINT.to_string(), + vec![], + None, + ) + .await; assert!(r.is_ok()); } @@ -121,6 +142,8 @@ async fn call_with_contract_address() { let config = KatanaRunnerConfig::default().with_db_dir("/tmp/spawn-and-move-db"); let sequencer = KatanaRunner::new_with_config(config).expect("Failed to start runner."); + let ui = Ui::new(scarb_ui::Verbosity::Verbose, scarb_ui::OutputFormat::Text); + let world = setup::setup_with_world(&sequencer).await.unwrap(); let provider = sequencer.provider(); let world_reader = WorldContractReader::new(world.address, provider); @@ -133,6 +156,7 @@ async fn call_with_contract_address() { assert!( call::call( + &ui, world_reader, format!("{:#x}", contract_address), ENTRYPOINT.to_string(), diff --git a/examples/spawn-and-move/Scarb.lock b/examples/spawn-and-move/Scarb.lock index 7a80ac1c79..8bcf917cfe 100644 --- a/examples/spawn-and-move/Scarb.lock +++ b/examples/spawn-and-move/Scarb.lock @@ -24,7 +24,7 @@ dependencies = [ [[package]] name = "dojo_examples" -version = "1.0.0-alpha.4" +version = "1.0.0-alpha.8" dependencies = [ "armory", "bestiary", diff --git a/examples/spawn-and-move/Scarb.toml b/examples/spawn-and-move/Scarb.toml index e1e536520c..81bd2d0585 100644 --- a/examples/spawn-and-move/Scarb.toml +++ b/examples/spawn-and-move/Scarb.toml @@ -1,7 +1,7 @@ [package] cairo-version = "=2.7.0" name = "dojo_examples" -version = "1.0.0-alpha.4" +version = "1.0.0-alpha.8" # Use the prelude with the less imports as possible # from corelib. edition = "2024_07" diff --git a/scripts/clippy.sh b/scripts/clippy.sh index 8b3cdbc299..43f9b5f208 100755 --- a/scripts/clippy.sh +++ b/scripts/clippy.sh @@ -8,7 +8,7 @@ set -x set -o pipefail run_clippy() { - cargo +nightly clippy --all-targets "$@" -- -D warnings -D future-incompatible -D nonstandard-style -D rust-2018-idioms -D unused -D missing-debug-implementations + cargo +nightly-2024-08-28 clippy --all-targets "$@" -- -D warnings -D future-incompatible -D nonstandard-style -D rust-2018-idioms -D unused -D missing-debug-implementations } run_clippy --all-features --workspace diff --git a/scripts/rust_fmt.sh b/scripts/rust_fmt.sh index 62a418693a..db5636de2e 100755 --- a/scripts/rust_fmt.sh +++ b/scripts/rust_fmt.sh @@ -1,3 +1,3 @@ #!/bin/bash -cargo +nightly fmt --check --all -- "$@" +cargo +nightly-2024-08-28 fmt --check --all -- "$@"