Sablier

Sablier
DeFiFoundry
53,440 USDC
View results
Submission Details
Severity: low
Invalid

Direct Admin Transfer in transferAdmin() Function

Summary

The transferAdmin() function transfers ownership directly to a new admin without utilizing a two-step transfer process. This transfer can introduce potential risks and lacks the safeguards provided by a more secure two-step transfer method.

Vulnerability Details

The transferAdmin() function is designed to transfer the admin role to a new address. However, it does this in a single step:

function transferAdmin(address newAdmin) public virtual override onlyAdmin {
// Effect: update the admin.
admin = newAdmin;
// Log the transfer of the admin.
emit IAdminable.TransferAdmin({ oldAdmin: msg.sender, newAdmin: newAdmin });
}

In the current implementation, the function directly assigns the new admin address and emits a transfer event. This lacks the confirmation step where the new admin would accept the role, which is a common practice to ensure the new admin address is correct and intended.

Impact

The direct transfer of admin rights without a confirmation step can lead to several issues:

  • Accidental Transfers: The admin might accidentally transfer ownership to an incorrect address, potentially losing control over the contract.

  • Security Risks: If the current admin's private key is compromised, an attacker can immediately transfer the admin rights to themselves or another malicious address.

  • Lack of Revert Mechanism: There is no opportunity for the current admin to revert the transfer if the new admin address is invalid or incorrect.

Tools Used

Manual Code Review

Recommendations

To mitigate the identified risks, it is recommended to implement a two-step transfer process for the admin role. This typically involves the following steps:

  1. Initiate Transfer: The current admin initiates the transfer by setting a pending admin address.

  2. Accept Transfer: The new admin confirms the transfer by accepting the role.

Here is an example of how this can be implemented:

address public pendingAdmin;
function initiateTransferAdmin(address newAdmin) public onlyAdmin {
pendingAdmin = newAdmin;
emit InitiateTransferAdmin(msg.sender, newAdmin);
}
function acceptTransferAdmin() public {
require(msg.sender == pendingAdmin, "Only the pending admin can accept the transfer");
emit IAdminable.TransferAdmin(admin, pendingAdmin);
admin = pendingAdmin;
pendingAdmin = address(0);
}
Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

Info/Gas/Invalid as per Docs

https://docs.codehawks.com/hawks-auditors/how-to-determine-a-finding-validity

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.