The setOrganizer function lacks proper safeguards and can transfer critical permissions to invalid addresses, potentially locking out legitimate organizers or enabling malicious takeovers.
function setOrganizer(address _organizer) public onlyOwner {
@> organizer = _organizer;
@>
@>
@>
}
modifier onlyOrganizer() {
@> require(msg.sender == organizer, "Only organizer can call this");
_;
}
function testOrganizerLockout() public {
vm.startPrank(owner);
address wrongAddress = address(0xdead);
festival.setOrganizer(wrongAddress);
vm.stopPrank();
vm.startPrank(organizer);
vm.expectRevert("Only organizer can call this");
festival.createPerformance(block.timestamp + 1 hours, 1 hours, 100 ether);
vm.stopPrank();
vm.startPrank(wrongAddress);
vm.expectRevert();
festival.createPerformance(block.timestamp + 1 hours, 1 hours, 100 ether);
vm.stopPrank();
}
function testMaliciousOrganizerTakeover() public {
address maliciousActor = makeAddr("malicious");
vm.startPrank(owner);
festival.setOrganizer(maliciousActor);
vm.stopPrank();
vm.startPrank(maliciousActor);
festival.createPerformance(block.timestamp + 1 hours, 1 hours, type(uint256).max);
festival.configurePass(GENERAL_PASS, 1 wei, type(uint256).max);
vm.stopPrank();
}
+ address public pendingOrganizer;
+ uint256 public organizerChangeDelay = 2 days;
+ uint256 public pendingOrganizerTimestamp;
+ event OrganizerChangeInitiated(address indexed newOrganizer, uint256 effectiveTime);
+ event OrganizerChanged(address indexed oldOrganizer, address indexed newOrganizer);
- function setOrganizer(address _organizer) public onlyOwner {
- organizer = _organizer;
- }
+ function initiateOrganizerChange(address _newOrganizer) public onlyOwner {
+ require(_newOrganizer != address(0), "Invalid organizer address");
+ require(_newOrganizer != organizer, "Same organizer");
+
+ pendingOrganizer = _newOrganizer;
+ pendingOrganizerTimestamp = block.timestamp + organizerChangeDelay;
+
+ emit OrganizerChangeInitiated(_newOrganizer, pendingOrganizerTimestamp);
+ }
+ function acceptOrganizerRole() public {
+ require(msg.sender == pendingOrganizer, "Not pending organizer");
+ require(block.timestamp >= pendingOrganizerTimestamp, "Change delay not met");
+
+ address oldOrganizer = organizer;
+ organizer = pendingOrganizer;
+ pendingOrganizer = address(0);
+ pendingOrganizerTimestamp = 0;
+
+ emit OrganizerChanged(oldOrganizer, organizer);
+ }
+ function cancelOrganizerChange() public onlyOwner {
+ pendingOrganizer = address(0);
+ pendingOrganizerTimestamp = 0;
+ }