From 3eff1016c924984390feda23a788f420399690dd Mon Sep 17 00:00:00 2001 From: notV4l Date: Tue, 3 Oct 2023 20:31:19 +0200 Subject: [PATCH] feat: add some world events --- crates/dojo-core/src/world.cairo | 74 ++++++++++-- .../dojo-lang/src/manifest_test_data/manifest | 112 +++++++++++++++++- 2 files changed, 174 insertions(+), 12 deletions(-) diff --git a/crates/dojo-core/src/world.cairo b/crates/dojo-core/src/world.cairo index b9af5dbfa8..b1a832cae4 100644 --- a/crates/dojo-core/src/world.cairo +++ b/crates/dojo-core/src/world.cairo @@ -8,7 +8,7 @@ trait IWorld { fn set_metadata_uri(ref self: T, resource: felt252, uri: Span); fn model(self: @T, name: felt252) -> ClassHash; fn register_model(ref self: T, class_hash: ClassHash); - fn deploy_contract(self: @T, salt: felt252, class_hash: ClassHash) -> ContractAddress; + fn deploy_contract(ref self: T, salt: felt252, class_hash: ClassHash) -> ContractAddress; fn uuid(ref self: T) -> usize; fn emit(self: @T, keys: Array, values: Span); fn entity( @@ -73,10 +73,14 @@ mod world { #[derive(Drop, starknet::Event)] enum Event { WorldSpawned: WorldSpawned, + ContractDeployed: ContractDeployed, MetadataUpdate: MetadataUpdate, ModelRegistered: ModelRegistered, StoreSetRecord: StoreSetRecord, - StoreDelRecord: StoreDelRecord + StoreDelRecord: StoreDelRecord, + WriterUpdated: WriterUpdated, + OwnerUpdated: OwnerUpdated, + ExecutorUpdated: ExecutorUpdated } #[derive(Drop, starknet::Event)] @@ -85,6 +89,13 @@ mod world { creator: ContractAddress } + #[derive(Drop, starknet::Event)] + struct ContractDeployed { + salt: felt252, + class_hash: ClassHash, + address: ContractAddress, + } + #[derive(Drop, starknet::Event)] struct MetadataUpdate { resource: felt252, @@ -94,7 +105,8 @@ mod world { #[derive(Drop, starknet::Event)] struct ModelRegistered { name: felt252, - class_hash: ClassHash + class_hash: ClassHash, + prev_class_hash: ClassHash } #[derive(Drop, starknet::Event)] @@ -111,6 +123,27 @@ mod world { keys: Span, } + #[derive(Drop, starknet::Event)] + struct WriterUpdated { + model: felt252, + system: ContractAddress, + value: bool + } + + #[derive(Drop, starknet::Event)] + struct OwnerUpdated { + address: ContractAddress, + resource: felt252, + value: bool, + } + + #[derive(Drop, starknet::Event)] + struct ExecutorUpdated { + address: ContractAddress, + prev_address: ContractAddress, + } + + #[storage] struct Storage { executor_dispatcher: IExecutorDispatcher, @@ -232,7 +265,9 @@ mod world { fn grant_owner(ref self: ContractState, address: ContractAddress, resource: felt252) { let caller = get_caller_address(); assert(self.is_owner(caller, resource) || self.is_owner(caller, WORLD), 'not owner'); - self.owners.write((resource, address), bool::True(())); + self.owners.write((resource, address), true); + + EventEmitter::emit(ref self, OwnerUpdated { address, resource, value: true }); } /// Revokes owner permission to the system for the model. @@ -246,6 +281,8 @@ mod world { let caller = get_caller_address(); assert(self.is_owner(caller, resource) || self.is_owner(caller, WORLD), 'not owner'); self.owners.write((resource, address), bool::False(())); + + EventEmitter::emit(ref self, OwnerUpdated { address, resource, value: false }); } /// Checks if the provided system is a writer of the model. @@ -275,7 +312,9 @@ mod world { assert( self.is_owner(caller, model) || self.is_owner(caller, WORLD), 'not owner or writer' ); - self.writers.write((model, system), bool::True(())); + self.writers.write((model, system), true); + + EventEmitter::emit(ref self, WriterUpdated { model, system, value: true }); } /// Revokes writer permission to the system for the model. @@ -294,7 +333,9 @@ mod world { || self.is_owner(caller, WORLD), 'not owner or writer' ); - self.writers.write((model, system), bool::False(())); + self.writers.write((model, system), false); + + EventEmitter::emit(ref self, WriterUpdated { model, system, value: false }); } /// Registers a model in the world. If the model is already registered, @@ -307,16 +348,19 @@ mod world { let caller = get_caller_address(); let calldata = ArrayTrait::new(); let name = *class_call(@self, class_hash, NAME_ENTRYPOINT, calldata.span())[0]; + let mut prev_class_hash = starknet::class_hash::ClassHashZeroable::zero(); // If model is already registered, validate permission to update. - if self.models.read(name).is_non_zero() { + let current_class_hash = self.models.read(name); + if current_class_hash.is_non_zero() { assert(self.is_owner(caller, name), 'only owner can update'); + prev_class_hash = current_class_hash; } else { - self.owners.write((name, caller), bool::True(())); + self.owners.write((name, caller), true); }; self.models.write(name, class_hash); - EventEmitter::emit(ref self, ModelRegistered { name, class_hash }); + EventEmitter::emit(ref self, ModelRegistered { name, class_hash, prev_class_hash }); } /// Gets the class hash of a registered model. @@ -343,7 +387,7 @@ mod world { /// /// * `ClassHash` - The class hash of the model. fn deploy_contract( - self: @ContractState, salt: felt252, class_hash: ClassHash + ref self: ContractState, salt: felt252, class_hash: ClassHash ) -> ContractAddress { let (contract_address, _) = deploy_syscall( self.contract_base.read(), salt, array![].span(), false @@ -351,6 +395,11 @@ mod world { .unwrap_syscall(); let upgradable_dispatcher = IUpgradeableDispatcher { contract_address }; upgradable_dispatcher.upgrade(class_hash); + + EventEmitter::emit( + ref self, ContractDeployed { salt, class_hash, address: contract_address } + ); + contract_address } @@ -481,9 +530,14 @@ mod world { fn set_executor(ref self: ContractState, contract_address: ContractAddress) { // Only owner can set executor assert(self.is_owner(get_caller_address(), WORLD), 'only owner can set executor'); + let prev_address = self.executor_dispatcher.read().contract_address; self .executor_dispatcher .write(IExecutorDispatcher { contract_address: contract_address }); + + EventEmitter::emit( + ref self, ExecutorUpdated { address: contract_address, prev_address } + ); } /// Gets the executor contract address. diff --git a/crates/dojo-lang/src/manifest_test_data/manifest b/crates/dojo-lang/src/manifest_test_data/manifest index 06acbfbd23..36d2a0bcfe 100644 --- a/crates/dojo-lang/src/manifest_test_data/manifest +++ b/crates/dojo-lang/src/manifest_test_data/manifest @@ -8,7 +8,7 @@ test_manifest_file "world": { "name": "world", "address": null, - "class_hash": "0x31c46921215521820397313c5130b8522a1f2b1e19e58c6025b57a86851539c", + "class_hash": "0x5f14aacb2bc68686eca3b024df6b79acfa8755976c9d99967af6fb99b650b8", "abi": [ { "type": "impl", @@ -155,7 +155,7 @@ test_manifest_file "type": "core::starknet::contract_address::ContractAddress" } ], - "state_mutability": "view" + "state_mutability": "external" }, { "type": "function", @@ -463,6 +463,28 @@ test_manifest_file } ] }, + { + "type": "event", + "name": "dojo::world::world::ContractDeployed", + "kind": "struct", + "members": [ + { + "name": "salt", + "type": "core::felt252", + "kind": "data" + }, + { + "name": "class_hash", + "type": "core::starknet::class_hash::ClassHash", + "kind": "data" + }, + { + "name": "address", + "type": "core::starknet::contract_address::ContractAddress", + "kind": "data" + } + ] + }, { "type": "event", "name": "dojo::world::world::MetadataUpdate", @@ -494,6 +516,11 @@ test_manifest_file "name": "class_hash", "type": "core::starknet::class_hash::ClassHash", "kind": "data" + }, + { + "name": "prev_class_hash", + "type": "core::starknet::class_hash::ClassHash", + "kind": "data" } ] }, @@ -541,6 +568,67 @@ test_manifest_file } ] }, + { + "type": "event", + "name": "dojo::world::world::WriterUpdated", + "kind": "struct", + "members": [ + { + "name": "model", + "type": "core::felt252", + "kind": "data" + }, + { + "name": "system", + "type": "core::starknet::contract_address::ContractAddress", + "kind": "data" + }, + { + "name": "value", + "type": "core::bool", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::world::world::OwnerUpdated", + "kind": "struct", + "members": [ + { + "name": "address", + "type": "core::starknet::contract_address::ContractAddress", + "kind": "data" + }, + { + "name": "resource", + "type": "core::felt252", + "kind": "data" + }, + { + "name": "value", + "type": "core::bool", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::world::world::ExecutorUpdated", + "kind": "struct", + "members": [ + { + "name": "address", + "type": "core::starknet::contract_address::ContractAddress", + "kind": "data" + }, + { + "name": "prev_address", + "type": "core::starknet::contract_address::ContractAddress", + "kind": "data" + } + ] + }, { "type": "event", "name": "dojo::world::world::Event", @@ -551,6 +639,11 @@ test_manifest_file "type": "dojo::world::world::WorldSpawned", "kind": "nested" }, + { + "name": "ContractDeployed", + "type": "dojo::world::world::ContractDeployed", + "kind": "nested" + }, { "name": "MetadataUpdate", "type": "dojo::world::world::MetadataUpdate", @@ -570,6 +663,21 @@ test_manifest_file "name": "StoreDelRecord", "type": "dojo::world::world::StoreDelRecord", "kind": "nested" + }, + { + "name": "WriterUpdated", + "type": "dojo::world::world::WriterUpdated", + "kind": "nested" + }, + { + "name": "OwnerUpdated", + "type": "dojo::world::world::OwnerUpdated", + "kind": "nested" + }, + { + "name": "ExecutorUpdated", + "type": "dojo::world::world::ExecutorUpdated", + "kind": "nested" } ] }