Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/finding #2 Fix Calculating Salt #124

Merged

Conversation

Aboudjem
Copy link
Contributor

@Aboudjem Aboudjem commented Aug 1, 2024

This PR addresses security audit finding #2 regarding non-deterministic salt computation in the createAccount function across several factory contracts. The following updates were made:

  • K1ValidatorFactory:

    • Updated NatSpec documentation.
    • Fixed non-deterministic salt issue by ensuring all parameters are correctly hashed together.
  • NexusAccountFactory:

    • Rewritten assembly code for correct salt computation.
    • Added missing NatSpec documentation.
  • RegistryFactory:

    • Corrected assembly code for deterministic salt computation.
    • Optimized gas usage by changing isModuleAllowed from public to private.
  • Test Cases:

    • Added tests to verify that manually computed addresses match those generated by the updated computeAccountAddress function, ensuring the correctness of the salt computation fix.

Copy link

openzeppelin-code bot commented Aug 1, 2024

Fix/finding #2 Fix Calculating Salt

Generated at commit: 9024384c238c7ce92105726fc62988fd885875d3

🚨 Report Summary

Severity Level Results
Contracts Critical
High
Medium
Low
Note
Total
0
1
0
6
24
31

For more details view the full report in OpenZeppelin Code Inspector

Copy link

codecov bot commented Aug 1, 2024

Codecov Report

Attention: Patch coverage is 85.71429% with 2 lines in your changes missing coverage. Please review.

Please upload report for BASE (remediations/cantina-spearbit@ad6af35). Learn more about missing BASE report.

Files Patch % Lines
contracts/factory/RegistryFactory.sol 75.00% 2 Missing ⚠️
Additional details and impacted files
@@                       Coverage Diff                        @@
##             remediations/cantina-spearbit     #124   +/-   ##
================================================================
  Coverage                                 ?   75.73%           
================================================================
  Files                                    ?       13           
  Lines                                    ?      643           
  Branches                                 ?      148           
================================================================
  Hits                                     ?      487           
  Misses                                   ?      156           
  Partials                                 ?        0           
Files Coverage Δ
contracts/factory/K1ValidatorFactory.sol 100.00% <100.00%> (ø)
contracts/factory/NexusAccountFactory.sol 100.00% <100.00%> (ø)
contracts/factory/RegistryFactory.sol 80.48% <75.00%> (ø)

Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update ad6af35...9024384. Read the comment docs.

mstore(0x40, add(ptr, calldataLength))
calldatacopy(ptr, 0x04, calldataLength)
actualSalt := keccak256(ptr, calldataLength)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not quite sure why these two are not the same?

I believe this change was done only for gas optimisation from gaslite suggestion.

Copy link

@ankurdubey521 ankurdubey521 Aug 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you're effectively calculating keccak256(abi.encode(...params)) while his code is keccak256(abi.encodePacked(...params). Generally encodePack-ing is cheaper but I can't say for sure in this case if re-encoding will be cheaper than copying and hashing pre-encoded data. Best to look at benchmarks.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

check how arrays are abi encoded, there's an offset to the data (that can be chosen by the caller as the issue says) and you'd be encoding this offset too along with everything else.

@livingrockrises
Copy link
Contributor

audit finding #2 is linked wrong. it links to some issue

calldatacopy(ptr, 0x04, calldataLength)
actualSalt := keccak256(ptr, calldataLength)
// Store initData at the free memory pointer
calldatacopy(ptr, initData.offset, initData.length)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not consistent everywhere?
here it would be
bytes32 actualSalt = keccak256(abi.encodePacked(initData, salt))

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's what it does but in assembly

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean, why cant we just use this abi.encodePacked way everywhere then.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's for gas mostly.

But where else it's not used?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

like in other factories we have changed and used like this
bytes32 actualSalt = keccak256(abi.encodePacked(eoaOwner, index, attesters, threshold));

go back to the issue please to also understand test case needs.
we are still hashing everything for salt event without any change, but in the event it would be emitted different value which won't help to reconstruct salt

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@livingrockrises livingrockrises changed the title Fix/finding #2 Fix Salt Determinism Fix/finding #2 Fix Calculating Salt Aug 10, 2024
@@ -42,14 +42,17 @@ contract NexusAccountFactory is Stakeable, INexusFactory {
/// @param salt Unique salt for the Smart Account creation.
/// @return The address of the newly created Nexus account.
function createAccount(bytes calldata initData, bytes32 salt) external payable override returns (address payable) {
// Compute the actual salt for deterministic deployment
// Compute the actual salt as the hash of initData and salt using assembly
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

whats wrong with this comment

// Compute the actual salt for deterministic deployment

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed it to reflect the changes, as we use hash of initData and Salt only (without sig func)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for deterministic deployment

Is nice and consistent..

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -11,5 +11,7 @@ TestK1ValidatorFactory_Deployments
│ └── it should return the expected address
├── when creating an account with the same owner and index
│ └── it should result in the same address
└── when creating accounts with different indexes
└── it should result in different addresses
├── when creating accounts with different indexes
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think tests should confirm that you're able to compute same account address using the initData and salt index emitted in the events.

or could be different params depending on the factory/method but you get the gist.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The written tests are valid in my opinion

Copy link
Contributor

@livingrockrises livingrockrises left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

review i

Copy link

@VGabriel45 VGabriel45 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Aboudjem look over Chirag's comments

@Aboudjem
Copy link
Contributor Author

please check

Copy link

🤖 Slither Analysis Report 🔎

Slither report

# Slither report

THIS CHECKLIST IS NOT COMPLETE. Use --show-ignored-findings to show all the results.
Summary

constable-states

Impact: Optimization
🔴 Confidence: High

base/RegistryAdapter.sol#L12

factory/RegistryFactory.sol#L39

_This comment was automatically generated by the GitHub Actions workflow._

@livingrockrises livingrockrises merged commit 0070740 into remediations/cantina-spearbit Aug 16, 2024
9 of 10 checks passed
@livingrockrises livingrockrises deleted the fix/finding-2-salt-determinism branch August 16, 2024 13:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants