diff --git a/crates/dojo-lang/src/compiler.rs b/crates/dojo-lang/src/compiler.rs index 72eb562d5f..20c36e6a1a 100644 --- a/crates/dojo-lang/src/compiler.rs +++ b/crates/dojo-lang/src/compiler.rs @@ -7,6 +7,7 @@ use cairo_lang_compiler::db::RootDatabase; use cairo_lang_filesystem::db::FilesGroup; use cairo_lang_filesystem::ids::{CrateId, CrateLongId}; use cairo_lang_semantic::db::SemanticGroup; +use cairo_lang_starknet::abi; use cairo_lang_starknet::contract::{find_contracts, ContractDeclaration}; use cairo_lang_starknet::contract_class::{compile_prepared_db, ContractClass}; use cairo_lang_utils::UpcastMut; @@ -85,7 +86,8 @@ impl Compiler for DojoCompiler { }; // (contract name, class hash) - let mut compiled_classes: HashMap = HashMap::new(); + let mut compiled_classes: HashMap)> = + HashMap::new(); for (decl, class) in zip(contracts, classes) { let target_name = &unit.target().name; @@ -96,10 +98,10 @@ impl Compiler for DojoCompiler { serde_json::to_writer_pretty(file.deref_mut(), &class) .with_context(|| format!("failed to serialize contract: {contract_name}"))?; - let class_hash = compute_class_hash_of_contract_class(class).with_context(|| { + let class_hash = compute_class_hash_of_contract_class(&class).with_context(|| { format!("problem computing class hash for contract `{contract_name}`") })?; - compiled_classes.insert(contract_name, class_hash); + compiled_classes.insert(contract_name, (class_hash, class.abi)); } let mut file = target_dir.open_rw("manifest.json", "output file", ws.config())?; @@ -111,7 +113,7 @@ impl Compiler for DojoCompiler { } } -fn compute_class_hash_of_contract_class(class: ContractClass) -> Result { +fn compute_class_hash_of_contract_class(class: &ContractClass) -> Result { let class_str = serde_json::to_string(&class)?; let sierra_class = serde_json::from_str::(&class_str) .map_err(|e| anyhow!("error parsing Sierra class: {e}"))?; diff --git a/crates/dojo-lang/src/manifest.rs b/crates/dojo-lang/src/manifest.rs index 65dd0977be..69396c432a 100644 --- a/crates/dojo-lang/src/manifest.rs +++ b/crates/dojo-lang/src/manifest.rs @@ -5,6 +5,7 @@ use cairo_lang_defs::ids::{ModuleId, ModuleItemId}; use cairo_lang_filesystem::ids::CrateId; use cairo_lang_semantic::db::SemanticGroup; use cairo_lang_semantic::plugin::DynPluginAuxData; +use cairo_lang_starknet::abi; use convert_case::{Case, Casing}; use dojo_world::manifest::{ Contract, Input, Output, System, EXECUTOR_CONTRACT_NAME, WORLD_CONTRACT_NAME, @@ -23,11 +24,11 @@ impl Manifest { pub fn new( db: &dyn SemanticGroup, crate_ids: &[CrateId], - compiled_classes: HashMap, + compiled_classes: HashMap)>, ) -> Self { let mut manifest = Manifest(dojo_world::manifest::Manifest::default()); - let world = compiled_classes.get(WORLD_CONTRACT_NAME).unwrap_or_else(|| { + let (world, world_abi) = compiled_classes.get(WORLD_CONTRACT_NAME).unwrap_or_else(|| { panic!( "{}", format!( @@ -36,20 +37,29 @@ impl Manifest { ) ); }); - let executor = compiled_classes.get(EXECUTOR_CONTRACT_NAME).unwrap_or_else(|| { - panic!( - "{}", - format!( - "Contract `{}` not found. Did you include `dojo` as a dependency?", - EXECUTOR_CONTRACT_NAME - ) - ); - }); - - manifest.0.world = - Contract { name: WORLD_CONTRACT_NAME.into(), address: None, class_hash: *world }; - manifest.0.executor = - Contract { name: EXECUTOR_CONTRACT_NAME.into(), address: None, class_hash: *executor }; + let (executor, executor_abi) = + compiled_classes.get(EXECUTOR_CONTRACT_NAME).unwrap_or_else(|| { + panic!( + "{}", + format!( + "Contract `{}` not found. Did you include `dojo` as a dependency?", + EXECUTOR_CONTRACT_NAME + ) + ); + }); + + manifest.0.world = Contract { + name: WORLD_CONTRACT_NAME.into(), + address: None, + class_hash: *world, + abi: world_abi.clone(), + }; + manifest.0.executor = Contract { + name: EXECUTOR_CONTRACT_NAME.into(), + address: None, + class_hash: *executor, + abi: executor_abi.clone(), + }; for crate_id in crate_ids { let modules = db.crate_modules(*crate_id); @@ -86,7 +96,7 @@ impl Manifest { db: &dyn SemanticGroup, aux_data: &DojoAuxData, module_id: ModuleId, - compiled_classes: &HashMap, + compiled_classes: &HashMap)>, ) { for component in &aux_data.components { let component = component.clone(); @@ -96,7 +106,7 @@ impl Manifest { { // It needs the `Component` suffix because we are // searching from the compiled contracts. - let class_hash = compiled_classes + let (class_hash, class_abi) = compiled_classes .get(name.to_case(Case::Snake).as_str()) .with_context(|| format!("Component {name} not found in target.")) .unwrap(); @@ -105,6 +115,7 @@ impl Manifest { name: component.name, members: component.members, class_hash: *class_hash, + abi: class_abi.clone(), }); } } @@ -115,7 +126,7 @@ impl Manifest { db: &dyn SemanticGroup, aux_data: &DojoAuxData, module_id: ModuleId, - compiled_classes: &HashMap, + compiled_classes: &HashMap)>, ) -> Result<()> { for SystemAuxData { name, dependencies } in &aux_data.systems { if let Ok(Some(ModuleItemId::Submodule(submodule_id))) = @@ -150,7 +161,7 @@ impl Manifest { vec![Output { ty: signature.return_type.format(db) }] }; - let class_hash = compiled_classes + let (class_hash, class_abi) = compiled_classes .get(name.as_str()) .with_context(|| format!("System {name} not found in target.")) .unwrap(); @@ -165,6 +176,7 @@ impl Manifest { .sorted_by(|a, b| a.name.cmp(&b.name)) .cloned() .collect::>(), + abi: class_abi.clone(), }); } } else { diff --git a/crates/dojo-world/src/manifest.rs b/crates/dojo-world/src/manifest.rs index 8e3e74795c..8ff9892095 100644 --- a/crates/dojo-world/src/manifest.rs +++ b/crates/dojo-world/src/manifest.rs @@ -3,6 +3,7 @@ use std::path::Path; use ::serde::{Deserialize, Serialize}; use anyhow::{anyhow, Result}; +use cairo_lang_starknet::abi; use dojo_types::component::Member; use dojo_types::system::Dependency; use serde_with::serde_as; @@ -46,6 +47,7 @@ pub struct Component { pub members: Vec, #[serde_as(as = "UfeHex")] pub class_hash: FieldElement, + pub abi: Option, } /// System input ABI. @@ -73,6 +75,7 @@ pub struct System { #[serde_as(as = "UfeHex")] pub class_hash: FieldElement, pub dependencies: Vec, + pub abi: Option, } #[serde_as] @@ -83,6 +86,7 @@ pub struct Contract { pub address: Option, #[serde_as(as = "UfeHex")] pub class_hash: FieldElement, + pub abi: Option, } #[serde_as] @@ -209,11 +213,13 @@ impl Manifest { name: WORLD_CONTRACT_NAME.into(), class_hash: world_class_hash, address: Some(world_address), + ..Default::default() }, executor: Contract { name: EXECUTOR_CONTRACT_NAME.into(), address: Some(executor_address), class_hash: executor_class_hash, + ..Default::default() }, }) } diff --git a/crates/dojo-world/src/migration/world_test.rs b/crates/dojo-world/src/migration/world_test.rs index 367442c6ef..cdd9f898c8 100644 --- a/crates/dojo-world/src/migration/world_test.rs +++ b/crates/dojo-world/src/migration/world_test.rs @@ -7,16 +7,22 @@ fn no_diff_when_local_and_remote_are_equal() { address: Some(77_u32.into()), class_hash: 66_u32.into(), name: WORLD_CONTRACT_NAME.into(), + ..Default::default() }; let executor_contract = Contract { address: Some(88_u32.into()), class_hash: 99_u32.into(), name: EXECUTOR_CONTRACT_NAME.into(), + ..Default::default() }; - let components = - vec![Component { members: vec![], name: "Component".into(), class_hash: 11_u32.into() }]; + let components = vec![Component { + members: vec![], + name: "Component".into(), + class_hash: 11_u32.into(), + ..Default::default() + }]; let systems = vec![System { name: "System".into(), class_hash: 22_u32.into(), ..Default::default() }]; @@ -49,8 +55,12 @@ fn diff_when_local_and_remote_are_different() { ..Default::default() }; - let components = - vec![Component { members: vec![], name: "Component".into(), class_hash: 11_u32.into() }]; + let components = vec![Component { + members: vec![], + name: "Component".into(), + class_hash: 11_u32.into(), + ..Default::default() + }]; let systems = vec![System { name: "System".into(), class_hash: 22_u32.into(), ..Default::default() }]; diff --git a/crates/torii/core/src/sql_test.rs b/crates/torii/core/src/sql_test.rs index 6e910a661b..d4b2f53cd1 100644 --- a/crates/torii/core/src/sql_test.rs +++ b/crates/torii/core/src/sql_test.rs @@ -56,6 +56,7 @@ async fn test_load_from_manifest(pool: SqlitePool) { name: "Test".into(), members: vec![Member { name: "test".into(), ty: "u32".into(), key: false }], class_hash: FieldElement::TWO, + ..Default::default() }) .await .unwrap(); @@ -82,6 +83,7 @@ async fn test_load_from_manifest(pool: SqlitePool) { outputs: vec![], class_hash: FieldElement::THREE, dependencies: vec![], + ..Default::default() }) .await .unwrap();