Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Event fields as key #2280

Closed
wants to merge 21 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 84 additions & 54 deletions crates/dojo-core/src/tests/world/resources.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use dojo::model::{Model, ResourceMetadata};
use dojo::utils::{bytearray_hash, entity_id_from_keys};
use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait, world};
use dojo::world::world::{
NamespaceRegistered, ModelRegistered, ModelUpgraded, MetadataUpdate, ContractDeployed,
Event, NamespaceRegistered, ModelRegistered, ModelUpgraded, MetadataUpdate, ContractDeployed,
ContractUpgraded
};
use dojo::contract::{IContractDispatcher, IContractDispatcherTrait};
Expand Down Expand Up @@ -51,7 +51,11 @@ fn test_set_metadata_resource_owner() {

assert_eq!(
starknet::testing::pop_log(world.contract_address),
Option::Some(MetadataUpdate { resource: metadata.resource_id, uri: metadata.metadata_uri })
Option::Some(
Event::MetadataUpdate(
MetadataUpdate { resource: metadata.resource_id, uri: metadata.metadata_uri }
)
)
);
}

Expand Down Expand Up @@ -137,17 +141,22 @@ fn test_register_model_for_namespace_owner() {
starknet::testing::set_contract_address(bob);
world.register_model(foo::TEST_CLASS_HASH.try_into().unwrap());

let event = starknet::testing::pop_log::<ModelRegistered>(world.contract_address);

assert(event.is_some(), 'no ModelRegistered event');
let event = event.unwrap();
assert(event.name == Model::<Foo>::name(), 'bad model name');
assert(event.namespace == Model::<Foo>::namespace(), 'bad model namespace');
assert(event.class_hash == foo::TEST_CLASS_HASH.try_into().unwrap(), 'bad model class_hash');
assert(
event.address != core::num::traits::Zero::<ContractAddress>::zero(),
'bad model prev address'
);
let event = starknet::testing::pop_log::<Event>(world.contract_address);
assert(event.is_some(), 'no event)');

if let Event::ModelRegistered(event) = event.unwrap() {
assert(event.name == Model::<Foo>::name(), 'bad model name');
assert(event.namespace == Model::<Foo>::namespace(), 'bad model namespace');
assert(
event.class_hash == foo::TEST_CLASS_HASH.try_into().unwrap(), 'bad model class_hash'
);
assert(
event.address != core::num::traits::Zero::<ContractAddress>::zero(),
'bad model prev address'
);
} else {
core::panic_with_felt252('no ModelRegistered event');
}

assert(world.is_owner(Model::<Foo>::selector(), bob), 'bob is not the owner');
}
Expand All @@ -165,17 +174,22 @@ fn test_register_model_for_namespace_writer() {
starknet::testing::set_contract_address(bob);
world.register_model(foo::TEST_CLASS_HASH.try_into().unwrap());

let event = starknet::testing::pop_log::<ModelRegistered>(world.contract_address);

assert(event.is_some(), 'no ModelRegistered event');
let event = event.unwrap();
assert(event.name == Model::<Foo>::name(), 'bad model name');
assert(event.namespace == Model::<Foo>::namespace(), 'bad model namespace');
assert(event.class_hash == foo::TEST_CLASS_HASH.try_into().unwrap(), 'bad model class_hash');
assert(
event.address != core::num::traits::Zero::<ContractAddress>::zero(),
'bad model prev address'
);
let event = starknet::testing::pop_log::<Event>(world.contract_address);
assert(event.is_some(), 'no event)');

if let Event::ModelRegistered(event) = event.unwrap() {
assert(event.name == Model::<Foo>::name(), 'bad model name');
assert(event.namespace == Model::<Foo>::namespace(), 'bad model namespace');
assert(
event.class_hash == foo::TEST_CLASS_HASH.try_into().unwrap(), 'bad model class_hash'
);
assert(
event.address != core::num::traits::Zero::<ContractAddress>::zero(),
'bad model prev address'
);
} else {
core::panic_with_felt252('no ModelRegistered event');
}

assert(world.is_owner(Model::<Foo>::selector(), bob), 'bob is not the owner');
}
Expand All @@ -195,17 +209,22 @@ fn test_upgrade_model_from_model_owner() {

world.upgrade_model(foo::TEST_CLASS_HASH.try_into().unwrap());

let event = starknet::testing::pop_log::<ModelUpgraded>(world.contract_address);

assert(event.is_some(), 'no ModelRegistered event');
let event = event.unwrap();
assert(event.name == Model::<Foo>::name(), 'bad model name');
assert(event.namespace == Model::<Foo>::namespace(), 'bad model namespace');
assert(event.class_hash == foo::TEST_CLASS_HASH.try_into().unwrap(), 'bad model class_hash');
assert(
event.address != core::num::traits::Zero::<ContractAddress>::zero(),
'bad model prev address'
);
let event = starknet::testing::pop_log::<Event>(world.contract_address);
assert(event.is_some(), 'no event)');

if let Event::ModelUpgraded(event) = event.unwrap() {
assert(event.name == Model::<Foo>::name(), 'bad model name');
assert(event.namespace == Model::<Foo>::namespace(), 'bad model namespace');
assert(
event.class_hash == foo::TEST_CLASS_HASH.try_into().unwrap(), 'bad model class_hash'
);
assert(
event.address != core::num::traits::Zero::<ContractAddress>::zero(),
'bad model prev address'
);
} else {
core::panic_with_felt252('no ModelRegistered event');
}

assert(world.is_owner(Model::<Foo>::selector(), bob), 'bob is not the owner');
}
Expand Down Expand Up @@ -291,13 +310,14 @@ fn test_register_namespace() {
let namespace = "namespace";
let hash = bytearray_hash(@namespace);

world.register_namespace(namespace);
world.register_namespace(namespace.clone());

assert(world.is_owner(hash, bob), 'namespace not registered');

let expected_event = NamespaceRegistered { namespace, hash };
assert_eq!(
starknet::testing::pop_log(world.contract_address),
Option::Some(NamespaceRegistered { namespace: "namespace", hash })
Option::Some(Event::NamespaceRegistered(expected_event))
);
}

Expand Down Expand Up @@ -349,16 +369,21 @@ fn test_deploy_contract_for_namespace_owner() {
let contract_address = world.deploy_contract('salt1', class_hash);
let dispatcher = IContractDispatcher { contract_address };

let event = starknet::testing::pop_log::<ContractDeployed>(world.contract_address);
assert(event.is_some(), 'no ContractDeployed event');
let event = event.unwrap();
assert(event.salt == 'salt1', 'bad event salt');
assert(event.class_hash == class_hash, 'bad class_hash');
assert(event.name == dispatcher.contract_name(), 'bad contract name');
assert(event.namespace == dispatcher.namespace(), 'bad namespace');
assert(
event.address != core::num::traits::Zero::<ContractAddress>::zero(), 'bad contract address'
);
let event = starknet::testing::pop_log::<Event>(world.contract_address);
assert(event.is_some(), 'no event)');

if let Event::ContractDeployed(event) = event.unwrap() {
assert(event.salt == 'salt1', 'bad event salt');
assert(event.class_hash == class_hash, 'bad class_hash');
assert(event.name == dispatcher.contract_name(), 'bad contract name');
assert(event.namespace == dispatcher.namespace(), 'bad namespace');
assert(
event.address != core::num::traits::Zero::<ContractAddress>::zero(),
'bad contract address'
);
} else {
core::panic_with_felt252('no ContractDeployed event');
};
}

#[test]
Expand Down Expand Up @@ -437,13 +462,18 @@ fn test_upgrade_contract_from_resource_owner() {

world.upgrade_contract(dispatcher.selector(), class_hash);

let event = starknet::testing::pop_log::<ContractUpgraded>(world.contract_address);
assert(event.is_some(), 'no ContractUpgraded event');
let event = event.unwrap();
assert(event.class_hash == class_hash, 'bad class_hash');
assert(
event.address != core::num::traits::Zero::<ContractAddress>::zero(), 'bad contract address'
);
let event = starknet::testing::pop_log::<Event>(world.contract_address);
assert(event.is_some(), 'no event)');

if let Event::ContractUpgraded(event) = event.unwrap() {
assert(event.class_hash == class_hash, 'bad class_hash');
assert(
event.address != core::num::traits::Zero::<ContractAddress>::zero(),
'bad contract address'
);
} else {
core::panic_with_felt252('no ContractUpgraded event');
};
}

#[test]
Expand Down
53 changes: 39 additions & 14 deletions crates/dojo-core/src/world/world_contract.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ pub mod world {
impl ConfigInternalImpl = Config::InternalImpl<ContractState>;

#[event]
#[derive(Drop, starknet::Event)]
#[derive(Drop, starknet::Event, Debug, PartialEq)]
pub enum Event {
WorldSpawned: WorldSpawned,
ContractDeployed: ContractDeployed,
Expand All @@ -158,36 +158,44 @@ pub mod world {
WriterUpdated: WriterUpdated,
OwnerUpdated: OwnerUpdated,
ConfigEvent: Config::Event,
StateUpdated: StateUpdated
StateUpdated: StateUpdated,
// Dojo System Events are emitted by the `emit!` macro.
// The selector is fixed to `selector!("dojo_core::event::SYSTEM_EVENT_SELECTOR")` and
// should not be used directly in this enumeration.
}

#[derive(Drop, starknet::Event)]
#[derive(Drop, starknet::Event, Debug, PartialEq)]
pub struct StateUpdated {
pub da_hash: felt252,
}

#[derive(Drop, starknet::Event)]
#[derive(Drop, starknet::Event, Debug, PartialEq)]
pub struct WorldSpawned {
pub address: ContractAddress,
#[key]
pub creator: ContractAddress
}

#[derive(Drop, starknet::Event)]
#[derive(Drop, starknet::Event, Debug, PartialEq)]
pub struct WorldUpgraded {
pub class_hash: ClassHash,
}

#[derive(Drop, starknet::Event, Debug, PartialEq)]
pub struct ContractDeployed {
pub salt: felt252,
#[key]
pub class_hash: ClassHash,
pub address: ContractAddress,
#[key]
pub namespace: ByteArray,
pub name: ByteArray
#[key]
pub name: ByteArray,
pub salt: felt252,
pub address: ContractAddress,
}

#[derive(Drop, starknet::Event, Debug, PartialEq)]
pub struct ContractUpgraded {
#[key]
pub class_hash: ClassHash,
pub address: ContractAddress,
}
Expand All @@ -200,19 +208,23 @@ pub mod world {

#[derive(Drop, starknet::Event, Debug, PartialEq)]
pub struct MetadataUpdate {
#[key]
pub resource: felt252,
pub uri: ByteArray
}

#[derive(Drop, starknet::Event, Debug, PartialEq)]
pub struct NamespaceRegistered {
#[key]
pub namespace: ByteArray,
pub hash: felt252
}

#[derive(Drop, starknet::Event, Debug, PartialEq)]
pub struct ModelRegistered {
#[key]
pub name: ByteArray,
#[key]
pub namespace: ByteArray,
pub class_hash: ClassHash,
pub address: ContractAddress,
Expand All @@ -228,44 +240,57 @@ pub mod world {
pub prev_address: ContractAddress,
}

#[derive(Drop, starknet::Event)]
#[derive(Drop, starknet::Event, Debug, PartialEq)]
pub struct StoreSetRecord {
#[key]
pub table: felt252,
#[key]
pub keys: Span<felt252>,
pub values: Span<felt252>,
}

#[derive(Drop, starknet::Event)]
#[derive(Drop, starknet::Event, Debug, PartialEq)]
pub struct StoreUpdateRecord {
#[key]
pub table: felt252,
#[key]
pub entity_id: felt252,
pub values: Span<felt252>,
}

#[derive(Drop, starknet::Event)]
#[derive(Drop, starknet::Event, Debug, PartialEq)]
pub struct StoreUpdateMember {
#[key]
pub table: felt252,
#[key]
pub entity_id: felt252,
#[key]
pub member_selector: felt252,
pub values: Span<felt252>,
}

#[derive(Drop, starknet::Event)]
#[derive(Drop, starknet::Event, Debug, PartialEq)]
pub struct StoreDelRecord {
#[key]
pub table: felt252,
#[key]
pub entity_id: felt252,
}

#[derive(Drop, starknet::Event)]
#[derive(Drop, starknet::Event, Debug, PartialEq)]
pub struct WriterUpdated {
#[key]
pub resource: felt252,
#[key]
pub contract: ContractAddress,
pub value: bool
}

#[derive(Drop, starknet::Event)]
#[derive(Drop, starknet::Event, Debug, PartialEq)]
pub struct OwnerUpdated {
#[key]
pub address: ContractAddress,
#[key]
pub resource: felt252,
pub value: bool,
}
Expand Down
6 changes: 6 additions & 0 deletions crates/dojo-lang/src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use cairo_lang_starknet_classes::abi::EventFieldKind;
use cairo_lang_syntax::node::db::SyntaxGroup;
use cairo_lang_syntax::node::helpers::QueryAttrs;
use cairo_lang_syntax::node::{ast, Terminal, TypedStablePtr, TypedSyntaxNode};
use dojo_types::event::SYSTEM_EVENT_SELECTOR;
use indoc::formatdoc;

use crate::plugin::DojoAuxData;
Expand Down Expand Up @@ -75,6 +76,9 @@ pub fn handle_event_struct(
(
// Append the event selector using the struct_name for the selector
// and then append the members.
//
// The first key of a dojo event will be the selector for SYSTEM_EVENT_SELECTOR,
// to distinguish them from starknet events.
RewriteNode::interpolate_patched(
&formatdoc!(
"
Expand All @@ -83,6 +87,8 @@ pub fn handle_event_struct(
self: @$struct_name$, ref keys: Array<felt252>, ref data: Array<felt252>
) {{
core::array::ArrayTrait::append(ref keys, \
selector!(\"{SYSTEM_EVENT_SELECTOR}\"));
core::array::ArrayTrait::append(ref keys, \
dojo::model::Model::<$struct_name$>::selector());
$append_members$
}}
Expand Down
Loading
Loading