58579 sc low inconsistent admin management implementation in alchemistcurator sol
Submitted on Nov 3rd 2025 at 10:35:51 UTC by @Ratt13snak3 for Audit Comp | Alchemix V3
Report ID: #58579
Report Type: Smart Contract
Report severity: Low
Target: https://github.com/alchemix-finance/v3-poc/blob/immunefi_audit/src/AlchemistCurator.sol
Impacts:
Permanent freezing of funds
Contract fails to deliver promised returns, but doesn't lose value
Description
Description
The AlchemistCurator contract inherits from PermissionedProxy, which already defines a one-step admin update function:
function setAdmin(address _admin) external onlyAdmin {
require(_admin != address(0), "zero");
admin = _admin;
emit AdminUpdated(_admin);
}However, AlchemistCurator adds an entirely new two-step admin transfer mechanism using:
This introduces two competing methods for admin management: a one-step (setAdmin) and a two-step (transferAdminOwnerShip + acceptAdminOwnership). Both modify the same admin variable and are callable by the DAO (the admin), which can cause confusion, governance errors, or unintended privilege transfers if both flows are used inconsistently.
Impact : Administrative confusion and potential misconfiguration
DAO (admin) may mistakenly assume a two-step admin handover is enforced, when in fact the inherited
setAdmin()can instantly replace the admin.
Recommendation
If the intent is to use a two-step transfer model, remove or disable the setAdmin() function from PermissionedProxy. Alternatively, standardize on the single-step setAdmin() and delete transferAdminOwnerShip() and acceptAdminOwnership() from the curator.
Proof of Concept
Proof of Concept
insert the test function below into AlchemistCurator.t.sol
then run the test:
Was this helpful?