-
Notifications
You must be signed in to change notification settings - Fork 12.2k
Add ERC7579 Validators #5891
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
base: master
Are you sure you want to change the base?
Add ERC7579 Validators #5891
Changes from all commits
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 |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'openzeppelin-solidity': minor | ||
--- | ||
|
||
`ERC7579Signature`: Add implementation of `ERC7579Validator` that enables ERC-7579 accounts to integrate with address-less cryptographic keys and account signatures through ERC-7913 signature verification. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'openzeppelin-solidity': minor | ||
--- | ||
|
||
`ERC7579Validator`: Add abstract validator module for ERC-7579 accounts that provides base implementation for signature validation. |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,86 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// SPDX-License-Identifier: MIT | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
pragma solidity ^0.8.27; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import {IERC7579Module} from "../../interfaces/draft-IERC7579.sol"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import {SignatureChecker} from "../../utils/cryptography/SignatureChecker.sol"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import {ERC7579Validator} from "./ERC7579Validator.sol"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* @dev Implementation of {ERC7579Validator} module using ERC-7913 signature verification. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* This validator allows ERC-7579 accounts to integrate with address-less cryptographic keys | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* and account signatures through the ERC-7913 signature verification system. Each account | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* can store its own ERC-7913 formatted signer (a concatenation of a verifier address and a | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* key: `verifier || key`). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* This enables accounts to use signature schemes without requiring each key to have its own | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* Ethereum address.A smart account with this module installed can keep an emergency key as a | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* backup. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
contract ERC7579Signature is ERC7579Validator { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
mapping(address account => bytes signer) private _signers; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// @dev Emitted when the signer is set. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
event ERC7579SignatureSignerSet(address indexed account, bytes signer); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// @dev Thrown when the signer length is less than 20 bytes. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
error ERC7579SignatureInvalidSignerLength(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// @dev Return the ERC-7913 signer (i.e. `verifier || key`). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
function signer(address account) public view virtual returns (bytes memory) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return _signers[account]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* @dev See {IERC7579Module-onInstall}. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* NOTE: An account can only call onInstall once. If called directly by the account, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* the signer will be set to the provided data. Future installations will behave as a no-op. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
function onInstall(bytes calldata data) public virtual { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (signer(msg.sender).length == 0) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
setSigner(data); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* @dev See {IERC7579Module-onUninstall}. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* WARNING: The signer's key will be removed if the account calls this function, potentially | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* making the account unusable. As an account operator, make sure to uninstall to a predefined path | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* in your account that properly handles side effects of uninstallation. See {AccountERC7579-uninstallModule}. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
function onUninstall(bytes calldata) public virtual { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_setSigner(msg.sender, ""); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// @dev Sets the ERC-7913 signer (i.e. `verifier || key`) for the calling account. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
function setSigner(bytes memory signer_) public virtual { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
require(signer_.length >= 20, ERC7579SignatureInvalidSignerLength()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+59
to
+60
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. suggestion: The minimum signer length check may not be sufficient for all ERC-7913 use cases. ERC-7913 signers may require more specific validation based on verifier and key format. Please consider adding stricter checks or documenting the expected signer structure to avoid misconfiguration. Suggested implementation:
You will need to define the custom error error ERC7579SignatureInvalidVerifier(); Also, ensure that the expected structure of the signer (verifier || key) is documented wherever relevant in your codebase and documentation. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_setSigner(msg.sender, signer_); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+58
to
+62
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. Custom error with require will not compile; use revert. require(..., CustomError()) is invalid. Switch to an explicit revert. - function setSigner(bytes memory signer_) public virtual {
- require(signer_.length >= 20, ERC7579SignatureInvalidSignerLength());
- _setSigner(msg.sender, signer_);
- }
+ function setSigner(bytes memory signer_) public virtual {
+ if (signer_.length < 20) revert ERC7579SignatureInvalidSignerLength();
+ _setSigner(msg.sender, signer_);
+ } 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/// @dev Internal version of {setSigner} that takes an `account` as argument without validating `signer_`. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
function _setSigner(address account, bytes memory signer_) internal virtual { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_signers[account] = signer_; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
emit ERC7579SignatureSignerSet(account, signer_); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* @dev See {ERC7579Validator-_rawERC7579Validation}. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* Validates a `signature` using ERC-7913 verification. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* This base implementation ignores the `sender` parameter and validates using | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* the account's stored signer. Derived contracts can override this to implement | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
* custom validation logic based on the sender. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
function _rawERC7579Validation( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
address account, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
bytes32 hash, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
bytes calldata signature | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) internal view virtual override returns (bool) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return SignatureChecker.isValidSignatureNow(signer(account), hash, signature); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+79
to
+86
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. suggestion: Signature validation relies on external SignatureChecker; ensure compatibility with all expected signer formats. Document the expected signer formats and cryptographic schemes, and consider adding extension points to support custom signature validation if needed.
Suggested change
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity ^0.8.27; | ||
|
||
import {IERC7579Module, IERC7579Validator, MODULE_TYPE_VALIDATOR} from "../../interfaces/draft-IERC7579.sol"; | ||
import {PackedUserOperation} from "../../interfaces/draft-IERC4337.sol"; | ||
import {ERC4337Utils} from "../../account/utils/draft-ERC4337Utils.sol"; | ||
import {IERC1271} from "../../interfaces/IERC1271.sol"; | ||
|
||
/** | ||
* @dev Abstract validator module for ERC-7579 accounts. | ||
* | ||
* This contract provides the base implementation for signature validation in ERC-7579 accounts. | ||
* Developers must implement the onInstall, onUninstall, and {_rawERC7579Validation} | ||
* functions in derived contracts to define the specific signature validation logic. | ||
* | ||
* Example usage: | ||
* | ||
* ```solidity | ||
* contract MyValidatorModule is ERC7579Validator { | ||
* function onInstall(bytes calldata data) public { | ||
* // Install logic here | ||
* } | ||
* | ||
* function onUninstall(bytes calldata data) public { | ||
* // Uninstall logic here | ||
* } | ||
* | ||
* function _rawERC7579Validation( | ||
* address account, | ||
* bytes32 hash, | ||
* bytes calldata signature | ||
* ) internal view override returns (bool) { | ||
* // Signature validation logic here | ||
* } | ||
* } | ||
* ``` | ||
* | ||
* Developers can restrict other operations by using the internal {_rawERC7579Validation}. | ||
* Example usage: | ||
* | ||
* ```solidity | ||
* function execute( | ||
* address account, | ||
* Mode mode, | ||
* bytes calldata executionCalldata, | ||
* bytes32 salt, | ||
* bytes calldata signature | ||
* ) public virtual { | ||
* require(_rawERC7579Validation(account, hash, signature)); | ||
* // ... rest of execute logic | ||
* } | ||
* ``` | ||
*/ | ||
abstract contract ERC7579Validator is IERC7579Module, IERC7579Validator { | ||
/// @inheritdoc IERC7579Module | ||
function isModuleType(uint256 moduleTypeId) public pure virtual returns (bool) { | ||
return moduleTypeId == MODULE_TYPE_VALIDATOR; | ||
} | ||
|
||
/// @inheritdoc IERC7579Validator | ||
function validateUserOp( | ||
PackedUserOperation calldata userOp, | ||
bytes32 userOpHash | ||
) public view virtual returns (uint256) { | ||
return | ||
_rawERC7579Validation(msg.sender, userOpHash, userOp.signature) | ||
? ERC4337Utils.SIG_VALIDATION_SUCCESS | ||
: ERC4337Utils.SIG_VALIDATION_FAILED; | ||
} | ||
|
||
/** | ||
* @dev See {IERC7579Validator-isValidSignatureWithSender}. | ||
* | ||
* Ignores the `sender` parameter and validates using {_rawERC7579Validation}. | ||
* Consider overriding this function to implement custom validation logic | ||
* based on the original sender. | ||
*/ | ||
function isValidSignatureWithSender( | ||
address /* sender */, | ||
bytes32 hash, | ||
bytes calldata signature | ||
) public view virtual returns (bytes4) { | ||
return | ||
_rawERC7579Validation(msg.sender, hash, signature) | ||
? IERC1271.isValidSignature.selector | ||
: bytes4(0xffffffff); | ||
} | ||
|
||
/** | ||
* @dev Validation algorithm. | ||
* | ||
* WARNING: Validation is a critical security function. Implementations must carefully | ||
* handle cryptographic verification to prevent unauthorized access. | ||
*/ | ||
function _rawERC7579Validation( | ||
address account, | ||
bytes32 hash, | ||
bytes calldata signature | ||
) internal view virtual returns (bool); | ||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,70 @@ | ||||||||||||||||||||||||||||
const { ethers } = require('hardhat'); | ||||||||||||||||||||||||||||
const { expect } = require('chai'); | ||||||||||||||||||||||||||||
const { SIG_VALIDATION_SUCCESS, SIG_VALIDATION_FAILURE } = require('../../helpers/erc4337'); | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
function shouldBehaveLikeERC7579Module() { | ||||||||||||||||||||||||||||
describe('behaves like ERC7579Module', function () { | ||||||||||||||||||||||||||||
it('identifies its module type correctly', async function () { | ||||||||||||||||||||||||||||
await expect(this.mock.isModuleType(this.moduleType)).to.eventually.be.true; | ||||||||||||||||||||||||||||
await expect(this.mock.isModuleType(999)).to.eventually.be.false; // Using random unassigned module type | ||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
it('handles installation, uninstallation, and re-installation', async function () { | ||||||||||||||||||||||||||||
await expect(this.mockFromAccount.onInstall(this.installData || '0x')).to.not.be.reverted; | ||||||||||||||||||||||||||||
await expect(this.mockFromAccount.onUninstall(this.uninstallData || '0x')).to.not.be.reverted; | ||||||||||||||||||||||||||||
await expect(this.mockFromAccount.onInstall(this.installData || '0x')).to.not.be.reverted; | ||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
function shouldBehaveLikeERC7579Validator() { | ||||||||||||||||||||||||||||
describe('behaves like ERC7579Validator', function () { | ||||||||||||||||||||||||||||
const MAGIC_VALUE = '0x1626ba7e'; | ||||||||||||||||||||||||||||
const INVALID_VALUE = '0xffffffff'; | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
beforeEach(async function () { | ||||||||||||||||||||||||||||
await this.mockFromAccount.onInstall(this.installData); | ||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
describe('validateUserOp', function () { | ||||||||||||||||||||||||||||
it('returns SIG_VALIDATION_SUCCESS when signature is valid', async function () { | ||||||||||||||||||||||||||||
const userOp = await this.mockAccount.createUserOp(this.userOp).then(op => this.signUserOp(op)); | ||||||||||||||||||||||||||||
await expect(this.mockFromAccount.validateUserOp(userOp.packed, userOp.hash())).to.eventually.equal( | ||||||||||||||||||||||||||||
SIG_VALIDATION_SUCCESS, | ||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
it('returns SIG_VALIDATION_FAILURE when signature is invalid', async function () { | ||||||||||||||||||||||||||||
const userOp = await this.mockAccount.createUserOp(this.userOp); | ||||||||||||||||||||||||||||
userOp.signature = this.invalidSignature || '0x00'; | ||||||||||||||||||||||||||||
await expect(this.mockFromAccount.validateUserOp(userOp.packed, userOp.hash())).to.eventually.equal( | ||||||||||||||||||||||||||||
SIG_VALIDATION_FAILURE, | ||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
describe('isValidSignatureWithSender', function () { | ||||||||||||||||||||||||||||
it('returns magic value for valid signature', async function () { | ||||||||||||||||||||||||||||
const message = 'Hello, world!'; | ||||||||||||||||||||||||||||
const hash = ethers.hashMessage(message); | ||||||||||||||||||||||||||||
const signature = await this.signer.signMessage(message); | ||||||||||||||||||||||||||||
await expect(this.mockFromAccount.isValidSignatureWithSender(this.other, hash, signature)).to.eventually.equal( | ||||||||||||||||||||||||||||
MAGIC_VALUE, | ||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
it('returns failure value for invalid signature', async function () { | ||||||||||||||||||||||||||||
const hash = ethers.hashMessage('Hello, world!'); | ||||||||||||||||||||||||||||
const signature = this.invalidSignature || '0x00'; | ||||||||||||||||||||||||||||
await expect(this.mock.isValidSignatureWithSender(this.other, hash, signature)).to.eventually.equal( | ||||||||||||||||||||||||||||
INVALID_VALUE, | ||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||
Comment on lines
+56
to
+61
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. 🛠️ Refactor suggestion Use mockFromAccount here for consistency with msg.sender-based validation. isValidSignatureWithSender relies on msg.sender (the account). Using this.mock may mask issues. - await expect(this.mock.isValidSignatureWithSender(this.other, hash, signature)).to.eventually.equal(
+ await expect(this.mockFromAccount.isValidSignatureWithSender(this.other, hash, signature)).to.eventually.equal(
INVALID_VALUE,
); 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
|
||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
module.exports = { | ||||||||||||||||||||||||||||
shouldBehaveLikeERC7579Module, | ||||||||||||||||||||||||||||
shouldBehaveLikeERC7579Validator, | ||||||||||||||||||||||||||||
}; |
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.
💡 Verification agent
🧩 Analysis chain
Verify package key matches the workspace configuration
Ensure
openzeppelin-solidity
is the correct package name in this repo’s Changesets config; otherwise use the actual workspace package (often@openzeppelin/contracts
).Run:
🏁 Script executed:
Length of output: 2180
🏁 Script executed:
Length of output: 590
🏁 Script executed:
Length of output: 890
Update Changesets to target the published package (@openzeppelin/contracts)
Your current setup is bumping the private root package (
name: "openzeppelin-solidity"
) instead of the actual npm package incontracts/package.json
(@openzeppelin/contracts
). To fix this, you need to tell Changesets about the subpackage and update all existing changesets to use its key.• In
.changeset/config.json
, add thepackages
field to point at thecontracts
folder:• Update each existing changeset in
.changeset/*.md
so that the first line uses the published package name. For example, inyummy-ideas-stay.md
:• Repeat for all files under
.changeset/
(e.g.witty-hats-flow.md
,whole-cats-find.md
, etc.).After these updates, running Changesets will correctly bump and publish
@openzeppelin/contracts
(version 5.4.0) instead of the private root.📝 Committable suggestion
🤖 Prompt for AI Agents