Skip to content

Commit a6a8dfc

Browse files
authored
Merge branch 'master' into typo-fixes
2 parents a1aa81b + 765b288 commit a6a8dfc

File tree

5 files changed

+23
-1
lines changed

5 files changed

+23
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
### Bug fixes
44

55
- `ERC165Checker`: Ensure the `supportsERC165` function returns false if the target reverts during the `supportsInterface(0xffffffff)` call. ([#5810](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5880))
6+
- `AccountERC7579`: Prevent revert in `isModuleInstalled` for fallback modules when `additionalContext` has fewer than 4 bytes. The function now returns `false` instead of reverting, ensuring ERC-7579 compliance. ([#5961](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5961))
67

78
### Breaking changes
89

contracts/account/extensions/draft-AccountERC7579.sol

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,9 @@ abstract contract AccountERC7579 is Account, IERC1271, IERC7579Execution, IERC75
149149
) public view virtual returns (bool) {
150150
if (moduleTypeId == MODULE_TYPE_VALIDATOR) return _validators.contains(module);
151151
if (moduleTypeId == MODULE_TYPE_EXECUTOR) return _executors.contains(module);
152-
if (moduleTypeId == MODULE_TYPE_FALLBACK) return _fallbacks[bytes4(additionalContext[0:4])] == module;
152+
if (moduleTypeId == MODULE_TYPE_FALLBACK)
153+
// ERC-7579 requires this function to return bool, never revert. Check length to avoid out-of-bounds access.
154+
return additionalContext.length > 3 && _fallbacks[bytes4(additionalContext[0:4])] == module;
153155
return false;
154156
}
155157

contracts/mocks/Stateless.sol

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import {ERC4337Utils} from "../account/utils/draft-ERC4337Utils.sol";
3333
import {ERC7579Utils} from "../account/utils/draft-ERC7579Utils.sol";
3434
import {ERC7913P256Verifier} from "../utils/cryptography/verifiers/ERC7913P256Verifier.sol";
3535
import {ERC7913RSAVerifier} from "../utils/cryptography/verifiers/ERC7913RSAVerifier.sol";
36+
import {ERC7913WebAuthnVerifier} from "../utils/cryptography/verifiers/ERC7913WebAuthnVerifier.sol";
3637
import {Heap} from "../utils/structs/Heap.sol";
3738
import {InteroperableAddress} from "../utils/draft-InteroperableAddress.sol";
3839
import {LowLevelCall} from "../utils/LowLevelCall.sol";

contracts/utils/cryptography/verifiers/ERC7913WebAuthnVerifier.sol

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import {IERC7913SignatureVerifier} from "../../../interfaces/IERC7913.sol";
1616
* WebAuthn checks: type validation, challenge matching, and cryptographic signature verification.
1717
*
1818
* NOTE: Wallets that may require default P256 validation may install a P256 verifier separately.
19+
*
20+
* @custom:stateless
1921
*/
2022
contract ERC7913WebAuthnVerifier is IERC7913SignatureVerifier {
2123
/// @inheritdoc IERC7913SignatureVerifier

test/account/extensions/AccountERC7579.behavior.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,22 @@ function shouldBehaveLikeAccountERC7579({ withHooks = false } = {}) {
9191
});
9292
});
9393

94+
describe('isModuleInstalled', function () {
95+
it('should not revert if calldata is empty or too short', async function () {
96+
await expect(
97+
this.mock.isModuleInstalled(MODULE_TYPE_FALLBACK, this.modules[MODULE_TYPE_FALLBACK], '0x'),
98+
).to.eventually.equal(false);
99+
100+
await expect(
101+
this.mock.isModuleInstalled(MODULE_TYPE_FALLBACK, this.modules[MODULE_TYPE_FALLBACK], '0x123456'),
102+
).to.eventually.equal(false);
103+
104+
await expect(
105+
this.mock.isModuleInstalled(MODULE_TYPE_FALLBACK, this.modules[MODULE_TYPE_FALLBACK], '0x12345678'),
106+
).to.eventually.equal(false);
107+
});
108+
});
109+
94110
describe('module installation', function () {
95111
it('should revert if the caller is not the canonical entrypoint or the account itself', async function () {
96112
await expect(this.mock.connect(this.other).installModule(MODULE_TYPE_VALIDATOR, this.mock, '0x'))

0 commit comments

Comments
 (0)