HardhatFoundry
30,000 USDC
View results
Submission Details
Severity: low
Valid

Missing `_isInitialized(msg.sender)` check in `K1Validator.transferOwnership()`

Summary

K1Validator.transferOwnership() does not check if the module is initialized for a smart account.

Vulnerability Details

K1Validator.transferOwnership() does not check if the module has been initialized for a smart account before setting smartAccountOwners to the new owner:

K1Validator.sol#L66-L71

function transferOwnership(address newOwner) external {
require(newOwner != address(0), ZeroAddressNotAllowed());
require(!_isContract(newOwner), NewOwnerIsContract());
smartAccountOwners[msg.sender] = newOwner;
}

Therefore, it is possible for a smart account to call transferOwnership() while the K1Validator module has not been initialized for it. If this occurs, it will no longer be possible for the module to be installed for the smart account, since onInstall() will revert due to the _isInitialized() check:

K1Validator.sol#L53

function onInstall(bytes calldata data) external {
require(data.length != 0, NoOwnerProvided());
require(!_isInitialized(msg.sender), ModuleAlreadyInitialized());

K1Validator.sol#L133-L135

function _isInitialized(address smartAccount) private view returns (bool) {
return smartAccountOwners[smartAccount] != address(0);
}

As such, a smart account could be permanently prevented from using a K1Validator module if it calls transferOwnership() before initialization.

A realistic scenario where this could occur:

  • Smart account owner sends a transaction calling transferOwnership().

  • The transaction is not executed for a long period of time.

  • Smart account owner sends a transaction calling uninstallModule() to uninstall the module:

    • onUninstall() is called, which resets the module to uninitialized.

  • The transaction calling transferOwnership() is executed afterwards.

  • Now, the smart account can no longer re-install the K1Validator module.

Impact

Smart accounts can be locked out of using the K1Validator module permanently.

Recommendations

In transferOwnership(), consider checking if the module is initialized for the calling smart account with _isInitialized(msg.sender).

Updates

Lead Judging Commences

0xnevi Lead Judge
11 months ago
0xnevi Lead Judge 11 months ago
Submission Judgement Published
Invalidated
Reason: Known issue

Appeal created

0xnevi Lead Judge
10 months ago
0xnevi Lead Judge 10 months ago
Submission Judgement Published
Validated
Assigned finding tags:

finding-isInitialized-uninstall-transfer-ownership

Support

FAQs

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