-
Notifications
You must be signed in to change notification settings - Fork 3
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
Changes from 8 commits
50c8b93
17ab61b
507810b
6015bfb
364bb0d
cf86649
c48ca23
7b8bdb9
4479307
9024384
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -42,14 +42,17 @@ | |
/// @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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. whats wrong with this comment // Compute the actual salt for deterministic deployment There was a problem hiding this comment. Choose a reason for hiding this commentThe 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) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. for deterministic deployment Is nice and consistent.. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
bytes32 actualSalt; | ||
assembly { | ||
// Load the free memory pointer | ||
let ptr := mload(0x40) | ||
let calldataLength := sub(calldatasize(), 0x04) | ||
mstore(0x40, add(ptr, calldataLength)) | ||
calldatacopy(ptr, 0x04, calldataLength) | ||
actualSalt := keccak256(ptr, calldataLength) | ||
// Store initData at the free memory pointer | ||
calldatacopy(ptr, initData.offset, initData.length) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why not consistent everywhere? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. that's what it does but in assembly There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's for gas mostly. But where else it's not used? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. like in other factories we have changed and used like this go back to the issue please to also understand test case needs. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
// Store salt after initData | ||
mstore(add(ptr, initData.length), salt) | ||
// Compute the keccak256 hash of the concatenated initData and salt | ||
actualSalt := keccak256(ptr, add(initData.length, 32)) | ||
} | ||
|
||
// Deploy the account using the deterministic address | ||
|
@@ -63,20 +66,22 @@ | |
} | ||
|
||
/// @notice Computes the expected address of a Nexus contract using the factory's deterministic deployment algorithm. | ||
/// @param - Initialization data to be called on the new Smart Account. | ||
/// @param - Unique salt for the Smart Account creation. | ||
/// @param initData - Initialization data to be called on the new Smart Account. | ||
/// @param salt - Unique salt for the Smart Account creation. | ||
/// @return expectedAddress The expected address at which the Nexus contract will be deployed if the provided parameters are used. | ||
function computeAccountAddress(bytes calldata, bytes32) external view override returns (address payable expectedAddress) { | ||
function computeAccountAddress(bytes calldata initData, bytes32 salt) external view override returns (address payable expectedAddress) { | ||
// Compute the actual salt for deterministic deployment | ||
bytes32 actualSalt; | ||
assembly { | ||
// Load the free memory pointer | ||
let ptr := mload(0x40) | ||
let calldataLength := sub(calldatasize(), 0x04) | ||
mstore(0x40, add(ptr, calldataLength)) | ||
calldatacopy(ptr, 0x04, calldataLength) | ||
actualSalt := keccak256(ptr, calldataLength) | ||
// Store initData at the free memory pointer | ||
calldatacopy(ptr, initData.offset, initData.length) | ||
// Store salt after initData | ||
mstore(add(ptr, initData.length), salt) | ||
// Compute the keccak256 hash of the concatenated initData and salt | ||
actualSalt := keccak256(ptr, add(initData.length, 32)) | ||
} | ||
|
||
expectedAddress = payable(LibClone.predictDeterministicAddressERC1967(ACCOUNT_IMPLEMENTATION, actualSalt, address(this))); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The written tests are valid in my opinion |
||
│ └── it should result in different addresses | ||
└── when manually computing the address using keccak256 | ||
└── it should match the address computed by computeAccountAddress |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 iskeccak256(abi.encodePacked(...params)
. GenerallyencodePack
-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.There was a problem hiding this comment.
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.