Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/wet-bottles-tie.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'openzeppelin-solidity': minor
---

`Account`: Add `signature` argument to the internal `_validateUserOp` function for custom signature handling logic.
12 changes: 9 additions & 3 deletions contracts/account/Account.sol
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ abstract contract Account is AbstractSigner, IAccount {
bytes32 userOpHash,
uint256 missingAccountFunds
) public virtual onlyEntryPoint returns (uint256) {
uint256 validationData = _validateUserOp(userOp, userOpHash);
uint256 validationData = _validateUserOp(userOp, userOpHash, userOp.signature);
_payPrefund(missingAccountFunds);
return validationData;
}
Expand All @@ -84,15 +84,21 @@ abstract contract Account is AbstractSigner, IAccount {
* @dev Returns the validationData for a given user operation. By default, this checks the signature of the
* signable hash (produced by {_signableUserOpHash}) using the abstract signer ({AbstractSigner-_rawSignatureValidation}).
*
* The `signature` parameter is taken directly from the user operation's `signature` field.
* This design enables derived contracts to implement custom signature handling logic,
* such as embedding additional data within the signature and processing it by overriding this function
* and optionally invoking `super`.
*
* NOTE: The userOpHash is assumed to be correct. Calling this function with a userOpHash that does not match the
* userOp will result in undefined behavior.
*/
function _validateUserOp(
PackedUserOperation calldata userOp,
bytes32 userOpHash
bytes32 userOpHash,
bytes calldata signature
) internal virtual returns (uint256) {
return
_rawSignatureValidation(_signableUserOpHash(userOp, userOpHash), userOp.signature)
_rawSignatureValidation(_signableUserOpHash(userOp, userOpHash), signature)
? ERC4337Utils.SIG_VALIDATION_SUCCESS
: ERC4337Utils.SIG_VALIDATION_FAILED;
}
Expand Down
5 changes: 3 additions & 2 deletions contracts/account/extensions/draft-AccountERC7579.sol
Original file line number Diff line number Diff line change
Expand Up @@ -207,13 +207,14 @@ abstract contract AccountERC7579 is Account, IERC1271, IERC7579Execution, IERC75
*/
function _validateUserOp(
PackedUserOperation calldata userOp,
bytes32 userOpHash
bytes32 userOpHash,
bytes calldata signature
) internal virtual override returns (uint256) {
address module = _extractUserOpValidator(userOp);
return
isModuleInstalled(MODULE_TYPE_VALIDATOR, module, Calldata.emptyBytes())
? IERC7579Validator(module).validateUserOp(userOp, _signableUserOpHash(userOp, userOpHash))
: super._validateUserOp(userOp, userOpHash);
: super._validateUserOp(userOp, userOpHash, signature);
}

/**
Expand Down
5 changes: 3 additions & 2 deletions contracts/mocks/account/AccountMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,10 @@ abstract contract AccountERC7702WithModulesMock is
{
function _validateUserOp(
PackedUserOperation calldata userOp,
bytes32 userOpHash
bytes32 userOpHash,
bytes calldata signature
) internal virtual override(Account, AccountERC7579) returns (uint256) {
return super._validateUserOp(userOp, userOpHash);
return super._validateUserOp(userOp, userOpHash, signature);
}

/// @dev Resolve implementation of ERC-1271 by both ERC7739 and AccountERC7579 to support both schemes.
Expand Down