Skip to content

Commit

Permalink
Add guardians Vec
Browse files Browse the repository at this point in the history
  • Loading branch information
obatirou committed Nov 26, 2024
1 parent fa028eb commit 6604148
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 15 deletions.
27 changes: 23 additions & 4 deletions cairo/protocol_handler/src/protocol_handler.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,12 @@ pub trait IProtocolHandler<TContractState> {
pub mod ProtocolHandler {
use starknet::event::EventEmitter;
use starknet::account::Call;
use starknet::{ContractAddress, ClassHash, get_block_timestamp, SyscallResultTrait};
use starknet::{
ContractAddress, contract_address_const, ClassHash, get_block_timestamp, SyscallResultTrait
};
use starknet::storage::{
Map, StoragePointerReadAccess, StoragePointerWriteAccess, StorageMapReadAccess,
StorageMapWriteAccess
StorageMapWriteAccess, Vec, MutableVecTrait
};
use openzeppelin_access::accesscontrol::AccessControlComponent;
use openzeppelin_introspection::src5::SRC5Component;
Expand Down Expand Up @@ -179,7 +181,7 @@ pub mod ProtocolHandler {
pub kakarot: IKakarotDispatcher,
pub security_council: ContractAddress,
pub operator: ContractAddress,
pub guardians: Map<ContractAddress, bool>,
pub guardians: Vec<ContractAddress>,
pub gas_price_admin: ContractAddress,
pub protocol_frozen_until: u64,
pub authorized_operator_selector: Map<felt252, bool>,
Expand Down Expand Up @@ -261,11 +263,14 @@ pub mod ProtocolHandler {
gas_price_admin: ContractAddress,
mut guardians: Span<ContractAddress>
) {
// Store the Kakarot, security council, operator and gas price admin addresses
// Store the Kakarot, security council, operator, gas price admin and guardians addresses
self.kakarot.write(IKakarotDispatcher { contract_address: kakarot });
self.security_council.write(security_council);
self.operator.write(operator);
self.gas_price_admin.write(gas_price_admin);
for guardian in guardians {
self.guardians.append().write(*guardian);
};

// Store the authorized selectors for the operator
self.authorized_operator_selector.write(selector!("set_native_token"), true);
Expand Down Expand Up @@ -492,6 +497,9 @@ pub mod ProtocolHandler {

// Grant the GUARDIAN_ROLE to the new guardian
self.accesscontrol._grant_role(GUARDIAN_ROLE, new_guardian_address);

// Add the guardian to the guardians list
self.guardians.append().write(new_guardian_address)
}

fn remove_guardian(ref self: ContractState, guardian_address: ContractAddress) {
Expand All @@ -500,6 +508,17 @@ pub mod ProtocolHandler {

// Revoke the GUARDIAN_ROLE from the guardian
self.accesscontrol._revoke_role(GUARDIAN_ROLE, guardian_address);

// Remove the guardian from the guardians list
for i in 0
..self
.guardians
.len() {
let guardian = self.guardians.at(i).read();
if guardian == guardian_address {
self.guardians.at(i).write(contract_address_const::<0>());
}
};
}
}
}
47 changes: 36 additions & 11 deletions cairo/protocol_handler/tests/test_protocol_handler.cairo
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use core::hash::{HashStateExTrait, HashStateTrait};
use core::pedersen::PedersenTrait;
use snforge_std::{
ContractClassTrait, ContractClass, declare, DeclareResultTrait, EventSpyTrait,
start_cheat_block_timestamp_global, start_cheat_caller_address, mock_call, spy_events, store,
Expand Down Expand Up @@ -656,12 +658,8 @@ fn test_protocol_handler_change_operator_should_pass() {
let access_control_dispatcher = IAccessControlDispatcher {
contract_address: protocol_handler.contract_address
};
assert!(
!access_control_dispatcher.has_role(ProtocolHandler::OPERATOR_ROLE, operator_mock()),
);
assert!(
access_control_dispatcher.has_role(ProtocolHandler::OPERATOR_ROLE, new_operator),
);
assert!(!access_control_dispatcher.has_role(ProtocolHandler::OPERATOR_ROLE, operator_mock()),);
assert!(access_control_dispatcher.has_role(ProtocolHandler::OPERATOR_ROLE, new_operator),);

// Check the Access control related events are emitted
let expected_revoked = AccessControlComponent::Event::RoleRevoked(
Expand Down Expand Up @@ -879,6 +877,20 @@ fn test_protocol_handler_add_guardian_should_pass() {
.with_contract_address(protocol_handler.contract_address)
.build();
contract_events.assert_emitted(@expected_granted);

// Check the guardian is added to the list
let length = load(
protocol_handler.contract_address,
selector!("guardians"),
1
);
assert_eq!(*length[0], (guardians_mock().len() + 1).into(), "Guardian not added");
// get storage slot for guardian
let storage_slot = PedersenTrait::new(selector!("guardians")).update_with(2).finalize();
let guardian3 = load(
protocol_handler.contract_address, storage_slot, 1
);
assert_eq!(*guardian3[0], new_guardian.into(), "Guardian not added");
}

#[test]
Expand All @@ -905,29 +917,42 @@ fn test_protocol_handler_remove_guardian_should_pass() {
// Spy on the events
let mut spy = spy_events();

// Call the protocol handler remove_guardian
let guardian = guardians_mock()[0];
protocol_handler.remove_guardian(*guardian);
// Ensure the guardian is in the list
let guardian_removed = *(guardians_mock()[0]);
let storage_slot = PedersenTrait::new(selector!("guardians")).update_with(0).finalize();
let guardian_loaded = load(
protocol_handler.contract_address, storage_slot, 1
);
assert_eq!(*guardian_loaded[0], guardian_removed.into(), "Guardian not in Vec");

// Remove the guardian
protocol_handler.remove_guardian(guardian_removed);

// Check the guardian is revoked
let access_control_dispatcher = IAccessControlDispatcher {
contract_address: protocol_handler.contract_address
};
assert(
!access_control_dispatcher.has_role(ProtocolHandler::GUARDIAN_ROLE, *guardian),
!access_control_dispatcher.has_role(ProtocolHandler::GUARDIAN_ROLE, guardian_removed),
'Guardian not revoked'
);

// Check the Access control related events are emitted
let expected_revoked = AccessControlComponent::Event::RoleRevoked(
RoleRevoked {
role: ProtocolHandler::GUARDIAN_ROLE,
account: *guardian,
account: guardian_removed,
sender: security_council_mock()
}
);
let contract_events = EventsFilterBuilderTrait::from_events(@spy.get_events())
.with_contract_address(protocol_handler.contract_address)
.build();
contract_events.assert_emitted(@expected_revoked);

// Check the guardian is set to 0 in the guardian list
let guardian_loaded = load(
protocol_handler.contract_address, storage_slot, 1
);
assert_eq!(*guardian_loaded[0], 0, "Guardian not in Vec");
}

0 comments on commit 6604148

Please sign in to comment.