SpiritVestingFactory::setTreasury() could be 2 factor, as well as the AccessControl OZ contract used in the codebase
Description:
SpiritVestingFactory::setTreasury() is single factor, so a single mistake can lose treasury access forever, which is responsible for cancelling the treasury in the SpiritVesting contract.
function setTreasury(address newTreasury) external onlyTreasury {
// Ensure the new treasury address is not the zero address
if (newTreasury == address(0)) revert FORBIDDEN();
treasury = newTreasury;
}Additionally, throughout the codebase, AccessControl is used, which also doesn't have 2 factor. The SpiritFactory is mostly stateless, besides the fact that it is a role in the RewardsController, so the ability to set staking pools could be compromised. The RewardController relies on roles for upgrades, rewards distributions, so it is also a pain point.
Impact:
Lost roles.
Recommended Mitigation:
Use the AccessControlDefaultAdminRules for better role management.