diff --git a/src/config/component.cairo b/src/config/component.cairo index ed078b9..cbede19 100644 --- a/src/config/component.cairo +++ b/src/config/component.cairo @@ -5,6 +5,8 @@ /// Errors. mod errors { const INVALID_CALLER: felt252 = 'Config: not owner or operator'; + const ALREADY_REGISTERED: felt252 = 'Config: already operator'; + const NOT_OPERATOR: felt252 = 'Config: not an operator'; } /// Configuration component. @@ -39,9 +41,16 @@ mod config_cpt { > of IConfig> { fn register_operator(ref self: ComponentState, address: ContractAddress) { get_dep_component!(@self, Ownable).assert_only_owner(); + assert(!self.operators.read(address), errors::ALREADY_REGISTERED); self.operators.write(address, true); } + fn unregister_operator(ref self: ComponentState, address: ContractAddress) { + get_dep_component!(@self, Ownable).assert_only_owner(); + assert(self.operators.read(address), errors::NOT_OPERATOR); + self.operators.write(address, false); + } + fn is_operator(self: @ComponentState, address: ContractAddress) -> bool { self.operators.read(address) } @@ -92,7 +101,7 @@ mod config_cpt { ref self: ComponentState, address: ContractAddress ) -> bool { let owner = get_dep_component!(@self, Ownable).owner(); - address == owner || self.operators.read(address) + address == owner || self.is_operator(address) } } } diff --git a/src/config/interface.cairo b/src/config/interface.cairo index 64df3a0..db90633 100644 --- a/src/config/interface.cairo +++ b/src/config/interface.cairo @@ -12,6 +12,8 @@ trait IConfig { /// * `address` - The operator account address. fn register_operator(ref self: T, address: ContractAddress); + fn unregister_operator(ref self: T, address: ContractAddress); + /// Verifies if the given address is an operator. /// # Arguments /// diff --git a/src/config/tests/test_config.cairo b/src/config/tests/test_config.cairo index eb692cd..5d5e2eb 100644 --- a/src/config/tests/test_config.cairo +++ b/src/config/tests/test_config.cairo @@ -15,7 +15,7 @@ fn deploy_mock() -> IConfigDispatcher { } #[test] -fn config_set_operator_ok() { +fn config_register_operator_ok() { let mock = deploy_mock(); assert(!mock.is_operator(c::OPERATOR()), 'expect not operator'); @@ -26,7 +26,7 @@ fn config_set_operator_ok() { } #[test] -fn config_set_multiple_operators_ok() { +fn config_register_multiple_operators_ok() { let mock = deploy_mock(); assert(!mock.is_operator(c::OPERATOR()), 'expect not operator'); assert(!mock.is_operator(c::OTHER()), 'expect not operator'); @@ -40,6 +40,37 @@ fn config_set_multiple_operators_ok() { assert(mock.is_operator(c::OTHER()), 'expect operator'); } +#[test] +fn config_unregister_operator_ok() { + let mock = deploy_mock(); + + snf::start_prank(CheatTarget::One(mock.contract_address), c::OWNER()); + + mock.register_operator(c::OPERATOR()); + assert(mock.is_operator(c::OPERATOR()), 'expect operator'); + + mock.unregister_operator(c::OPERATOR()); + assert(!mock.is_operator(c::OPERATOR()), 'expect not operator'); +} + +#[test] +fn config_unregister_multiple_operators_ok() { + let mock = deploy_mock(); + + snf::start_prank(CheatTarget::One(mock.contract_address), c::OWNER()); + + mock.register_operator(c::OPERATOR()); + mock.register_operator(c::OTHER()); + + assert(mock.is_operator(c::OPERATOR()), 'expect operator'); + assert(mock.is_operator(c::OTHER()), 'expect operator'); + + mock.unregister_operator(c::OPERATOR()); + mock.unregister_operator(c::OTHER()); + assert(!mock.is_operator(c::OPERATOR()), 'expect not operator'); + assert(!mock.is_operator(c::OTHER()), 'expect not operator'); +} + #[test] #[should_panic(expected: ('Caller is not the owner',))] fn config_set_operator_unauthorized() {