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

Incorrect Event Emission in `createAccount` Function of `NexusFactory.sol`

Summary

The NexusFactory.sol contract allows users to create smart accounts, but it only emits the AccountCreated event when the account is not already deployed. This results in a lack of transparency and traceability when accounts are deployed deterministically and already exist.

Vulnerability Details

The createAccount function in the NexusFactory.sol contract is responsible for creating smart accounts. It computes a deterministic address and checks if the account is already deployed. If the account is not already deployed, it initializes the account and emits the AccountCreated event. However, if the account is already deployed, no event is emitted.

Code Snippet

function createAccount(bytes calldata initData, bytes32 salt) external payable override returns (address payable) {
// Compute the actual salt for deterministic deployment
bytes32 actualSalt;
assembly {
let ptr := mload(0x40)
let calldataLength := sub(calldatasize(), 0x04)
mstore(0x40, add(ptr, calldataLength))
calldatacopy(ptr, 0x04, calldataLength)
actualSalt := keccak256(ptr, calldataLength)
}
// Deploy the account using the deterministic address
(bool alreadyDeployed, address account) = LibClone.createDeterministicERC1967(msg.value, ACCOUNT_IMPLEMENTATION, actualSalt);
if (!alreadyDeployed) {
INexus(account).initializeAccount(initData);
emit AccountCreated(account, initData, salt); // Event is emitted only if not already deployed
}
return payable(account);
}

Impact

The absence of the AccountCreated event emission for already deployed accounts can lead to:

  1. Potential Inconsistencies: Event-based off-chain systems relying on these events might miss critical information.

Recommendations

Emit the AccountCreated event regardless of whether the account was already deployed or not. This ensures transparency and traceability of all account creations.

Suggested Fix

function createAccount(bytes calldata initData, bytes32 salt) external payable override returns (address payable) {
// Compute the actual salt for deterministic deployment
bytes32 actualSalt;
assembly {
let ptr := mload(0x40)
let calldataLength := sub(calldatasize(), 0x04)
mstore(0x40, add(ptr, calldataLength))
calldatacopy(ptr, 0x04, calldataLength)
actualSalt := keccak256(ptr, calldataLength)
}
// Deploy the account using the deterministic address
(bool alreadyDeployed, address account) = LibClone.createDeterministicERC1967(msg.value, ACCOUNT_IMPLEMENTATION, actualSalt);
if (!alreadyDeployed) {
INexus(account).initializeAccount(initData);
}
emit AccountCreated(account, initData, salt); // Emit the event regardless of deployment status
return payable(account);
}

This modification ensures that the AccountCreated event is emitted for every account creation.

Updates

Lead Judging Commences

0xnevi Lead Judge
12 months ago
0xnevi Lead Judge 12 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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