Skip to content

Commit

Permalink
Update model register and contract deploy apis to take preimage
Browse files Browse the repository at this point in the history
  • Loading branch information
tarrencev committed Jan 6, 2024
1 parent 74c12c0 commit 4a0e3d2
Show file tree
Hide file tree
Showing 24 changed files with 197 additions and 174 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion crates/benches/contracts/src/actions.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ mod actions {
name: felt252,
}


#[external(v0)]
impl ActionsImpl of IActions<ContractState> {
fn spawn(self: @ContractState) {
Expand Down
4 changes: 2 additions & 2 deletions crates/dojo-core/src/base_test.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ fn deploy_world() -> IWorldDispatcher {
fn test_upgrade_from_world() {
let world = deploy_world();

let base_address = world.deploy_contract('salt', base::TEST_CLASS_HASH.try_into().unwrap());
let base_address = world.deploy_contract(array!['base'].span(), base::TEST_CLASS_HASH.try_into().unwrap());
let new_class_hash: ClassHash = contract_upgrade::TEST_CLASS_HASH.try_into().unwrap();

world.upgrade_contract(base_address, new_class_hash);
Expand All @@ -56,7 +56,7 @@ fn test_upgrade_from_world() {
fn test_upgrade_direct() {
let world = deploy_world();

let base_address = world.deploy_contract('salt', base::TEST_CLASS_HASH.try_into().unwrap());
let base_address = world.deploy_contract(array!['base'].span(), base::TEST_CLASS_HASH.try_into().unwrap());
let new_class_hash: ClassHash = contract_upgrade::TEST_CLASS_HASH.try_into().unwrap();

let upgradeable_dispatcher = IUpgradeableDispatcher { contract_address: base_address };
Expand Down
1 change: 0 additions & 1 deletion crates/dojo-core/src/database_test.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ use traits::{Into, TryInto};
use starknet::syscalls::deploy_syscall;
use starknet::class_hash::{Felt252TryIntoClassHash, ClassHash};
use dojo::world::{IWorldDispatcher};
use dojo::executor::executor;
use dojo::database::{get, set, set_with_index, del, scan};
use dojo::database::index::WhereCondition;

Expand Down
4 changes: 2 additions & 2 deletions crates/dojo-core/src/model.cairo
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
trait Model<T> {
fn name(self: @T) -> felt252;
fn name_hash(self: @T) -> felt252;
fn keys(self: @T) -> Span<felt252>;
fn values(self: @T) -> Span<felt252>;
fn layout(self: @T) -> Span<u8>;
Expand All @@ -8,7 +8,7 @@ trait Model<T> {

#[starknet::interface]
trait IModel<T> {
fn name(self: @T) -> felt252;
fn name_hash(self: @T) -> felt252;
fn layout(self: @T) -> Span<felt252>;
fn schema(self: @T) -> Span<dojo::database::introspect::Member>;
}
3 changes: 2 additions & 1 deletion crates/dojo-core/src/test_utils.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ fn spawn_test_world(models: Array<felt252>) -> IWorldDispatcher {
executor::TEST_CLASS_HASH.try_into().unwrap(), 0, constructor_calldata.span(), false
)
.unwrap();

// deploy world
let (world_address, _) = deploy_syscall(
world::TEST_CLASS_HASH.try_into().unwrap(),
Expand All @@ -63,7 +64,7 @@ fn spawn_test_world(models: Array<felt252>) -> IWorldDispatcher {
if index == models.len() {
break ();
}
world.register_model((*models[index]).try_into().unwrap());
world.register_model(array![index.into()].span(), (*models[index]).try_into().unwrap());
index += 1;
};

Expand Down
79 changes: 29 additions & 50 deletions crates/dojo-core/src/world.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ use option::OptionTrait;
trait IWorld<T> {
fn metadata_uri(self: @T, resource: felt252) -> Span<felt252>;
fn set_metadata_uri(ref self: T, resource: felt252, uri: Span<felt252>);
fn model(self: @T, name: felt252) -> ClassHash;
fn register_model(ref self: T, class_hash: ClassHash);
fn deploy_contract(ref self: T, salt: felt252, class_hash: ClassHash) -> ContractAddress;
fn model(self: @T, name_hash: felt252) -> ClassHash;
fn register_model(ref self: T, name: Span<felt252>, class_hash: ClassHash);
fn deploy_contract(ref self: T, name: Span<felt252>, class_hash: ClassHash) -> ContractAddress;
fn upgrade_contract(ref self: T, address: ContractAddress, class_hash: ClassHash) -> ClassHash;
fn uuid(ref self: T) -> usize;
fn emit(self: @T, keys: Array<felt252>, values: Span<felt252>);
Expand Down Expand Up @@ -47,7 +47,7 @@ trait IWorld<T> {

#[starknet::interface]
trait IUpgradeableWorld<T> {
fn upgrade(ref self: T, new_class_hash : ClassHash);
fn upgrade(ref self: T, new_class_hash: ClassHash);
}

#[starknet::interface]
Expand All @@ -70,19 +70,16 @@ mod world {
use starknet::{
get_caller_address, get_contract_address, get_tx_info,
contract_address::ContractAddressIntoFelt252, ClassHash, Zeroable, ContractAddress,
syscalls::{deploy_syscall, emit_event_syscall, replace_class_syscall}, SyscallResult, SyscallResultTrait,
SyscallResultTraitImpl
syscalls::{deploy_syscall, emit_event_syscall, replace_class_syscall}, SyscallResult,
SyscallResultTrait, SyscallResultTraitImpl
};

use dojo::database;
use dojo::database::index::WhereCondition;
use dojo::executor::{IExecutorDispatcher, IExecutorDispatcherTrait};
use dojo::world::{IWorldDispatcher, IWorld, IUpgradeableWorld};

use dojo::components::upgradeable::{IUpgradeableDispatcher, IUpgradeableDispatcherTrait};

const NAME_ENTRYPOINT: felt252 =
0x0361458367e696363fbcc70777d07ebbd2394e89fd0adcaf147faccd1d294d60;
use dojo::components::upgradeable::{IUpgradeableDispatcher, IUpgradeableDispatcherTrait};

const WORLD: felt252 = 0;

Expand Down Expand Up @@ -112,10 +109,10 @@ mod world {
struct WorldUpgraded {
class_hash: ClassHash,
}

#[derive(Drop, starknet::Event)]
struct ContractDeployed {
salt: felt252,
name: Span<felt252>,
class_hash: ClassHash,
address: ContractAddress,
}
Expand All @@ -134,7 +131,7 @@ mod world {

#[derive(Drop, starknet::Event)]
struct ModelRegistered {
name: felt252,
name: Span<felt252>,
class_hash: ClassHash,
prev_class_hash: ClassHash
}
Expand Down Expand Up @@ -173,7 +170,6 @@ mod world {
prev_address: ContractAddress,
}


#[storage]
struct Storage {
executor_dispatcher: IExecutorDispatcher,
Expand All @@ -195,24 +191,6 @@ mod world {
EventEmitter::emit(ref self, WorldSpawned { address: get_contract_address(), creator });
}

/// Call Helper,
/// Call the provided `entrypoint` method on the given `class_hash`.
///
/// # Arguments
///
/// * `class_hash` - Class Hash to call.
/// * `entrypoint` - Entrypoint to call.
/// * `calldata` - The calldata to pass.
///
/// # Returns
///
/// The return value of the call.
fn class_call(
self: @ContractState, class_hash: ClassHash, entrypoint: felt252, calldata: Span<felt252>
) -> Span<felt252> {
self.executor_dispatcher.read().call(class_hash, entrypoint, calldata)
}

#[external(v0)]
impl World of IWorld<ContractState> {
/// Returns the metadata URI of the world.
Expand Down Expand Up @@ -372,36 +350,35 @@ mod world {
/// # Arguments
///
/// * `class_hash` - The class hash of the model to be registered.
fn register_model(ref self: ContractState, class_hash: ClassHash) {
fn register_model(ref self: ContractState, name: Span<felt252>, class_hash: ClassHash) {
let caller = get_caller_address();
let calldata = ArrayTrait::new();
let name = *class_call(@self, class_hash, NAME_ENTRYPOINT, calldata.span())[0];
let name_hash = poseidon::poseidon_hash_span(name);
let mut prev_class_hash = starknet::class_hash::ClassHashZeroable::zero();

// If model is already registered, validate permission to update.
let current_class_hash = self.models.read(name);
let current_class_hash = self.models.read(name_hash);
if current_class_hash.is_non_zero() {
assert(self.is_owner(caller, name), 'only owner can update');
assert(self.is_owner(caller, name_hash), 'only owner can update');
prev_class_hash = current_class_hash;
} else {
self.owners.write((name, caller), true);
self.owners.write((name_hash, caller), true);
};

self.models.write(name, class_hash);
self.models.write(name_hash, class_hash);
EventEmitter::emit(ref self, ModelRegistered { name, class_hash, prev_class_hash });
}

/// Gets the class hash of a registered model.
///
/// # Arguments
///
/// * `name` - The name of the model.
/// * `name_hash` - The has of the model name.
///
/// # Returns
///
/// * `ClassHash` - The class hash of the model.
fn model(self: @ContractState, name: felt252) -> ClassHash {
self.models.read(name)
fn model(self: @ContractState, name_hash: felt252) -> ClassHash {
self.models.read(name_hash)
}

/// Deploys a contract associated with the world.
Expand All @@ -415,10 +392,11 @@ mod world {
///
/// * `ContractAddress` - The address of the newly deployed contract.
fn deploy_contract(
ref self: ContractState, salt: felt252, class_hash: ClassHash
ref self: ContractState, name: Span<felt252>, class_hash: ClassHash
) -> ContractAddress {
let name_hash = poseidon::poseidon_hash_span(name);
let (contract_address, _) = deploy_syscall(
self.contract_base.read(), salt, array![].span(), false
self.contract_base.read(), name_hash, array![].span(), false
)
.unwrap_syscall();
let upgradeable_dispatcher = IUpgradeableDispatcher { contract_address };
Expand All @@ -427,7 +405,7 @@ mod world {
self.owners.write((contract_address.into(), get_caller_address()), true);

EventEmitter::emit(
ref self, ContractDeployed { salt, class_hash, address: contract_address }
ref self, ContractDeployed { name, class_hash, address: contract_address }
);

contract_address
Expand Down Expand Up @@ -641,17 +619,18 @@ mod world {
/// # Arguments
///
/// * `new_class_hash` - The new world class hash.
fn upgrade(ref self: ContractState, new_class_hash : ClassHash){
fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {
assert(new_class_hash.is_non_zero(), 'invalid class_hash');
assert(IWorld::is_owner(@self, get_tx_info().unbox().account_contract_address, WORLD), 'only owner can upgrade');
assert(
IWorld::is_owner(@self, get_tx_info().unbox().account_contract_address, WORLD),
'only owner can upgrade'
);

// upgrade to new_class_hash
replace_class_syscall(new_class_hash).unwrap();

// emit Upgrade Event
EventEmitter::emit(
ref self, WorldUpgraded {class_hash: new_class_hash }
);
EventEmitter::emit(ref self, WorldUpgraded { class_hash: new_class_hash });
}
}

Expand Down
34 changes: 16 additions & 18 deletions crates/dojo-core/src/world_test.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ use starknet::{contract_address_const, ContractAddress, ClassHash, get_caller_ad
use starknet::syscalls::deploy_syscall;

use dojo::benchmarks;
use dojo::executor::executor;
use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait, world, IUpgradeableWorld, IUpgradeableWorldDispatcher, IUpgradeableWorldDispatcherTrait };
use dojo::world::{
IWorldDispatcher, IWorldDispatcherTrait, world, IUpgradeableWorld, IUpgradeableWorldDispatcher,
IUpgradeableWorldDispatcherTrait
};
use dojo::database::introspect::Introspect;
use dojo::test_utils::{spawn_test_world, deploy_with_world_address};
use dojo::benchmarks::{Character, end};
Expand Down Expand Up @@ -115,7 +117,7 @@ mod bar {
fn deploy_world_and_bar() -> (IWorldDispatcher, IbarDispatcher) {
// Spawn empty world
let world = deploy_world();
world.register_model(foo::TEST_CLASS_HASH.try_into().unwrap());
world.register_model(array!['foo'].span(), foo::TEST_CLASS_HASH.try_into().unwrap());

// System contract
let bar_contract = IbarDispatcher {
Expand All @@ -129,7 +131,7 @@ fn deploy_world_and_bar() -> (IWorldDispatcher, IbarDispatcher) {
#[available_gas(2000000)]
fn test_model() {
let world = deploy_world();
world.register_model(foo::TEST_CLASS_HASH.try_into().unwrap());
world.register_model(array!['foo'].span(), foo::TEST_CLASS_HASH.try_into().unwrap());
}

#[test]
Expand Down Expand Up @@ -167,9 +169,10 @@ fn test_delete() {
#[available_gas(6000000)]
fn test_model_class_hash_getter() {
let world = deploy_world();
world.register_model(foo::TEST_CLASS_HASH.try_into().unwrap());
let name = array!['foo'].span();
world.register_model(name, foo::TEST_CLASS_HASH.try_into().unwrap());

let foo = world.model('Foo');
let foo = world.model(poseidon::poseidon_hash_span(name));
assert(foo == foo::TEST_CLASS_HASH.try_into().unwrap(), 'foo does not exists');
}

Expand Down Expand Up @@ -212,7 +215,7 @@ fn test_set_entity_unauthorized() {
contract_address: deploy_with_world_address(bar::TEST_CLASS_HASH, world)
};

world.register_model(foo::TEST_CLASS_HASH.try_into().unwrap());
world.register_model(array!['foo'].span(), foo::TEST_CLASS_HASH.try_into().unwrap());

let caller = starknet::contract_address_const::<0x1337>();
starknet::testing::set_account_contract_address(caller);
Expand Down Expand Up @@ -502,10 +505,10 @@ mod worldupgrade {
struct Storage {
world: IWorldDispatcher,
}

#[external(v0)]
impl IWorldUpgradeImpl of super::IWorldUpgrade<ContractState> {
fn hello(self: @ContractState) -> felt252{
fn hello(self: @ContractState) -> felt252 {
'dojo'
}
}
Expand All @@ -515,7 +518,6 @@ mod worldupgrade {
#[test]
#[available_gas(60000000)]
fn test_upgradeable_world() {

// Deploy world contract
let world = deploy_world();

Expand All @@ -524,18 +526,15 @@ fn test_upgradeable_world() {
};
upgradeable_world_dispatcher.upgrade(worldupgrade::TEST_CLASS_HASH.try_into().unwrap());

let res = (IWorldUpgradeDispatcher {
contract_address: world.contract_address
}).hello();
let res = (IWorldUpgradeDispatcher { contract_address: world.contract_address }).hello();

assert(res == 'dojo', 'should return dojo');
}

#[test]
#[available_gas(60000000)]
#[should_panic(expected:('invalid class_hash', 'ENTRYPOINT_FAILED'))]
#[should_panic(expected: ('invalid class_hash', 'ENTRYPOINT_FAILED'))]
fn test_upgradeable_world_with_class_hash_zero() {

// Deploy world contract
let world = deploy_world();

Expand All @@ -549,9 +548,8 @@ fn test_upgradeable_world_with_class_hash_zero() {

#[test]
#[available_gas(60000000)]
#[should_panic( expected: ('only owner can upgrade', 'ENTRYPOINT_FAILED'))]
#[should_panic(expected: ('only owner can upgrade', 'ENTRYPOINT_FAILED'))]
fn test_upgradeable_world_from_non_owner() {

// Deploy world contract
let world = deploy_world();

Expand All @@ -563,4 +561,4 @@ fn test_upgradeable_world_from_non_owner() {
contract_address: world.contract_address
};
upgradeable_world_dispatcher.upgrade(worldupgrade::TEST_CLASS_HASH.try_into().unwrap());
}
}
2 changes: 1 addition & 1 deletion crates/dojo-lang/src/inline_macros/delete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ impl InlineMacroExprPlugin for DeleteMacro {
builder.add_str(&format!(
"
let __delete_macro_value__ = {};
{}.delete_entity(dojo::model::Model::name(@__delete_macro_value__),
{}.delete_entity(dojo::model::Model::name_hash(@__delete_macro_value__),
dojo::model::Model::keys(@__delete_macro_value__),
dojo::model::Model::layout(@__delete_macro_value__));",
entity,
Expand Down
2 changes: 1 addition & 1 deletion crates/dojo-lang/src/inline_macros/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ impl InlineMacroExprPlugin for SetMacro {
builder.add_str(&format!(
"
let __set_macro_value__ = {};
{}.set_entity(dojo::model::Model::name(@__set_macro_value__),
{}.set_entity(dojo::model::Model::name_hash(@__set_macro_value__),
dojo::model::Model::keys(@__set_macro_value__), 0_u8,
dojo::model::Model::values(@__set_macro_value__),
dojo::model::Model::layout(@__set_macro_value__));",
Expand Down
Loading

0 comments on commit 4a0e3d2

Please sign in to comment.