Skip to content

Commit

Permalink
add space manager component
Browse files Browse the repository at this point in the history
  • Loading branch information
pscott committed Oct 9, 2024
1 parent fff5cde commit f617ebb
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 81 deletions.
28 changes: 13 additions & 15 deletions starknet/src/execution_strategies/timelock.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ mod TimelockExecutionStrategy {
use sx::interfaces::IExecutionStrategy;
use super::ITimelockExecutionStrategy;
use sx::types::{Proposal, ProposalStatus};
use sx::utils::{simple_quorum::SimpleQuorumComponent, SpaceManager};
use sx::utils::{simple_quorum::SimpleQuorumComponent, space_manager::SpaceManagerComponent};

component!(path: OwnableComponent, storage: ownable, event: OwnableEvent);

Expand All @@ -44,6 +44,9 @@ mod TimelockExecutionStrategy {
impl SimpleQuorumImpl = SimpleQuorumComponent::SimpleQuorumImpl<ContractState>;
impl SimpleQuorumInternalImpl = SimpleQuorumComponent::InternalImpl<ContractState>;

component!(path: SpaceManagerComponent, storage: space_manager, event: SpaceManagerEvent);
impl SpaceManagerInternalImpl = SpaceManagerComponent::InternalImpl<ContractState>;

#[storage]
struct Storage {
_timelock_delay: u32,
Expand All @@ -53,6 +56,8 @@ mod TimelockExecutionStrategy {
ownable: OwnableComponent::Storage,
#[substorage(v0)]
simple_quorum: SimpleQuorumComponent::Storage,
#[substorage(v0)]
space_manager: SpaceManagerComponent::Storage,
}

#[event]
Expand All @@ -70,6 +75,8 @@ mod TimelockExecutionStrategy {
OwnableEvent: OwnableComponent::Event,
#[flat]
SimpleQuorumEvent: SimpleQuorumComponent::Event,
#[flat]
SpaceManagerEvent: SpaceManagerComponent::Event,
}

#[derive(Drop, PartialEq, starknet::Event)]
Expand Down Expand Up @@ -138,8 +145,7 @@ mod TimelockExecutionStrategy {

self.simple_quorum.initializer(quorum);

let mut state = SpaceManager::unsafe_new_contract_state();
SpaceManager::InternalImpl::initializer(ref state, spaces);
self.space_manager.initializer(spaces);

self._timelock_delay.write(timelock_delay);
self._veto_guardian.write(veto_guardian);
Expand All @@ -156,10 +162,7 @@ mod TimelockExecutionStrategy {
votes_abstain: u256,
payload: Array<felt252>
) {
// Migration to components planned ; disregard the `unsafe` keyword,
// it is actually safe.
let state = SpaceManager::unsafe_new_contract_state();
SpaceManager::InternalImpl::assert_only_spaces(@state);
self.space_manager.assert_only_spaces();
let proposal_status = self
.simple_quorum
.get_proposal_status(@proposal, votes_for, votes_against, votes_abstain);
Expand Down Expand Up @@ -296,21 +299,16 @@ mod TimelockExecutionStrategy {

fn enable_space(ref self: ContractState, space: ContractAddress) {
self.ownable.assert_only_owner();
let mut state = SpaceManager::unsafe_new_contract_state();
SpaceManager::InternalImpl::enable_space(ref state, space);
self.space_manager.enable_space(space);
}

fn disable_space(ref self: ContractState, space: ContractAddress) {
self.ownable.assert_only_owner();
let mut state = SpaceManager::unsafe_new_contract_state();
SpaceManager::InternalImpl::disable_space(ref state, space);
self.space_manager.disable_space(space);
}

fn is_space_enabled(self: @ContractState, space: ContractAddress) -> bool {
// Migration to components planned ; disregard the `unsafe` keyword,
// it is actually safe.
let state = SpaceManager::unsafe_new_contract_state();
SpaceManager::InternalImpl::is_space_enabled(@state, space)
self.space_manager.is_space_enabled(space)
}
}

Expand Down
1 change: 0 additions & 1 deletion starknet/src/lib.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,6 @@ mod utils {
use struct_hash::StructHash;

mod space_manager;
use space_manager::SpaceManager;
}

mod external {
Expand Down
138 changes: 73 additions & 65 deletions starknet/src/utils/space_manager.cairo
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#[starknet::contract]
mod SpaceManager {
#[starknet::component]
mod SpaceManagerComponent {
use starknet::{ContractAddress, info};

#[storage]
Expand All @@ -25,8 +25,12 @@ mod SpaceManager {
}

#[generate_trait]
impl InternalImpl of InternalTrait {
fn initializer(ref self: ContractState, mut spaces: Span<ContractAddress>) {
impl InternalImpl<
TContractState, +HasComponent<TContractState>
> of InternalTrait<TContractState> {
fn initializer(
ref self: ComponentState<TContractState>, mut spaces: Span<ContractAddress>
) {
loop {
match spaces.pop_front() {
Option::Some(space) => {
Expand All @@ -40,23 +44,23 @@ mod SpaceManager {
}
}

fn enable_space(ref self: ContractState, space: ContractAddress) {
fn enable_space(ref self: ComponentState<TContractState>, space: ContractAddress) {
assert(space.is_non_zero() && !self._spaces.read(space), 'Invalid Space');
self._spaces.write(space, true);
self.emit(Event::SpaceEnabled(SpaceEnabled { space: space }));
}

fn disable_space(ref self: ContractState, space: ContractAddress) {
fn disable_space(ref self: ComponentState<TContractState>, space: ContractAddress) {
assert(self._spaces.read(space), 'Invalid Space');
self._spaces.write(space, false);
self.emit(Event::SpaceDisabled(SpaceDisabled { space: space }));
}

fn is_space_enabled(self: @ContractState, space: ContractAddress) -> bool {
fn is_space_enabled(self: @ComponentState<TContractState>, space: ContractAddress) -> bool {
return self._spaces.read(space);
}

fn assert_only_spaces(self: @ContractState) {
fn assert_only_spaces(self: @ComponentState<TContractState>) {
assert(self._spaces.read(info::get_caller_address()), 'Unauthorized Space');
}
}
Expand All @@ -65,19 +69,43 @@ mod SpaceManager {
#[cfg(test)]
mod tests {
use starknet::{ContractAddress};
use super::SpaceManager;
use super::SpaceManagerComponent;
use super::SpaceManagerComponent::InternalTrait;

#[starknet::contract]
mod MockContract {
use super::SpaceManagerComponent;

component!(path: SpaceManagerComponent, storage: space_manager, event: SpaceManagerEvent);

#[storage]
struct Storage {
#[substorage(v0)]
space_manager: SpaceManagerComponent::Storage
}

#[event]
#[derive(Drop, starknet::Event)]
enum Event {
SpaceManagerEvent: SpaceManagerComponent::Event
}

impl SpaceManagerInternalImpl = SpaceManagerComponent::InternalImpl<ContractState>;
}

type ComponentState = SpaceManagerComponent::ComponentState<MockContract::ContractState>;

fn COMPONENT_STATE() -> ComponentState {
SpaceManagerComponent::component_state_for_testing()
}

#[test]
#[available_gas(10000000)]
fn initializer() {
let mut state = SpaceManager::unsafe_new_contract_state();
SpaceManager::InternalImpl::initializer(
ref state, array![starknet::contract_address_const::<0x123456789>()].span()
);
let mut state = COMPONENT_STATE();
state.initializer(array![starknet::contract_address_const::<0x123456789>()].span());
assert(
SpaceManager::InternalImpl::is_space_enabled(
@state, starknet::contract_address_const::<0x123456789>()
),
state.is_space_enabled(starknet::contract_address_const::<0x123456789>()),
'initializer failed'
);
}
Expand All @@ -86,39 +114,33 @@ mod tests {
#[available_gas(10000000)]
#[should_panic(expected: ('Invalid Space',))]
fn initializer_duplicate_address() {
let mut state = SpaceManager::unsafe_new_contract_state();
SpaceManager::InternalImpl::initializer(
ref state,
array![
starknet::contract_address_const::<0x123456789>(),
starknet::contract_address_const::<0x123456789>()
]
.span()
);
let mut state = COMPONENT_STATE();
state
.initializer(
array![
starknet::contract_address_const::<0x123456789>(),
starknet::contract_address_const::<0x123456789>()
]
.span()
);
}

#[test]
#[available_gas(10000000)]
#[should_panic(expected: ('Invalid Space',))]
fn initializer_zero_address() {
let mut state = SpaceManager::unsafe_new_contract_state();
SpaceManager::InternalImpl::initializer(
ref state, array![starknet::contract_address_const::<0x0>()].span()
);
let mut state = COMPONENT_STATE();
state.initializer(array![starknet::contract_address_const::<0x0>()].span());
}

#[test]
#[available_gas(10000000)]
fn enable_space() {
let mut state = SpaceManager::unsafe_new_contract_state();
SpaceManager::InternalImpl::initializer(ref state, array![].span());
SpaceManager::InternalImpl::enable_space(
ref state, starknet::contract_address_const::<0x123456789>()
);
let mut state = COMPONENT_STATE();
state.initializer(array![].span());
state.enable_space(starknet::contract_address_const::<0x123456789>());
assert(
SpaceManager::InternalImpl::is_space_enabled(
@state, starknet::contract_address_const::<0x123456789>()
),
state.is_space_enabled(starknet::contract_address_const::<0x123456789>()),
'enable_space failed'
);
}
Expand All @@ -127,41 +149,29 @@ mod tests {
#[available_gas(10000000)]
#[should_panic(expected: ('Invalid Space',))]
fn enable_space_duplicate_address() {
let mut state = SpaceManager::unsafe_new_contract_state();
SpaceManager::InternalImpl::initializer(ref state, array![].span());
SpaceManager::InternalImpl::enable_space(
ref state, starknet::contract_address_const::<0x123456789>()
);
SpaceManager::InternalImpl::enable_space(
ref state, starknet::contract_address_const::<0x123456789>()
);
let mut state = COMPONENT_STATE();
state.initializer(array![].span());
state.enable_space(starknet::contract_address_const::<0x123456789>());
state.enable_space(starknet::contract_address_const::<0x123456789>());
}

#[test]
#[available_gas(10000000)]
#[should_panic(expected: ('Invalid Space',))]
fn enable_space_zero_address() {
let mut state = SpaceManager::unsafe_new_contract_state();
SpaceManager::InternalImpl::initializer(ref state, array![].span());
SpaceManager::InternalImpl::enable_space(
ref state, starknet::contract_address_const::<0x0>()
);
let mut state = COMPONENT_STATE();
state.initializer(array![].span());
state.enable_space(starknet::contract_address_const::<0x0>());
}

#[test]
#[available_gas(10000000)]
fn disable_space() {
let mut state = SpaceManager::unsafe_new_contract_state();
SpaceManager::InternalImpl::initializer(
ref state, array![starknet::contract_address_const::<0x123456789>()].span()
);
SpaceManager::InternalImpl::disable_space(
ref state, starknet::contract_address_const::<0x123456789>()
);
let mut state = COMPONENT_STATE();
state.initializer(array![starknet::contract_address_const::<0x123456789>()].span());
state.disable_space(starknet::contract_address_const::<0x123456789>());
assert(
!SpaceManager::InternalImpl::is_space_enabled(
@state, starknet::contract_address_const::<0x123456789>()
),
!state.is_space_enabled(starknet::contract_address_const::<0x123456789>()),
'disable_space failed'
);
}
Expand All @@ -170,10 +180,8 @@ mod tests {
#[available_gas(10000000)]
#[should_panic(expected: ('Invalid Space',))]
fn disable_space_not_enabled() {
let mut state = SpaceManager::unsafe_new_contract_state();
SpaceManager::InternalImpl::initializer(ref state, array![].span());
SpaceManager::InternalImpl::disable_space(
ref state, starknet::contract_address_const::<0x123456789>()
);
let mut state = COMPONENT_STATE();
state.initializer(array![].span());
state.disable_space(starknet::contract_address_const::<0x123456789>());
}
}

0 comments on commit f617ebb

Please sign in to comment.