diff --git a/packages/core/solidity/src/account.test.ts b/packages/core/solidity/src/account.test.ts index e4dd16f95..72a76a992 100644 --- a/packages/core/solidity/src/account.test.ts +++ b/packages/core/solidity/src/account.test.ts @@ -50,7 +50,7 @@ test('account API assert defaults', async t => { t.is(account.print(account.defaults), account.print()); }); -for (const signer of [undefined, 'ERC7702', 'ECDSA', 'P256', 'RSA'] as const) { +for (const signer of [false, 'ERC7702', 'ECDSA', 'P256', 'RSA'] as const) { let title = 'Account'; if (signer) { title += ` with Signer${signer}`; @@ -102,6 +102,18 @@ for (const signer of [undefined, 'ERC7702', 'ECDSA', 'P256', 'RSA'] as const) { ERC7579Modules: 'AccountERC7579', }); + testAccount(`${title} with ERC7579 with ERC1271`, { + signer, + ERC7579Modules: 'AccountERC7579', + signatureValidation: 'ERC1271', + }); + + testAccount(`${title} with ERC7579 with ERC7739`, { + signer, + ERC7579Modules: 'AccountERC7579', + signatureValidation: 'ERC7739', + }); + testAccount(`${title} with ERC7579 hooks`, { signer, ERC7579Modules: 'AccountERC7579Hooked', diff --git a/packages/core/solidity/src/account.test.ts.md b/packages/core/solidity/src/account.test.ts.md index 8cbc7a7c3..bae9e7638 100644 --- a/packages/core/solidity/src/account.test.ts.md +++ b/packages/core/solidity/src/account.test.ts.md @@ -227,7 +227,83 @@ Generated by [AVA](https://avajs.dev). import {ERC7739} from "@openzeppelin/community-contracts/contracts/utils/cryptography/ERC7739.sol";␊ import {PackedUserOperation} from "@openzeppelin/contracts/interfaces/draft-IERC4337.sol";␊ ␊ - contract MyAccount is Account, EIP712, AccountERC7579, ERC7739 {␊ + contract MyAccount is Account, EIP712, ERC7739, AccountERC7579 {␊ + constructor() EIP712("MyAccount", "1") {}␊ + ␊ + function isValidSignature(bytes32 hash, bytes calldata signature)␊ + public␊ + view␊ + override(AccountERC7579, ERC7739)␊ + returns (bytes4)␊ + {␊ + // ERC-7739 can return the ERC-1271 magic value, 0xffffffff (invalid) or 0x77390001 (detection).␊ + // If the returned value is 0xffffffff, fallback to ERC-7579 validation.␊ + bytes4 erc7739magic = ERC7739.isValidSignature(hash, signature);␊ + return erc7739magic == bytes4(0xffffffff) ? AccountERC7579.isValidSignature(hash, signature) : erc7739magic;␊ + }␊ + ␊ + // The following functions are overrides required by Solidity.␊ + ␊ + function _validateUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash)␊ + internal␊ + override(Account, AccountERC7579)␊ + returns (uint256)␊ + {␊ + return super._validateUserOp(userOp, userOpHash);␊ + }␊ + }␊ + ` + +## Account with ERC7579 with ERC1271 + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts ^5.0.0␊ + pragma solidity ^0.8.27;␊ + ␊ + import {Account} from "@openzeppelin/community-contracts/contracts/account/Account.sol";␊ + import {AccountERC7579} from "@openzeppelin/community-contracts/contracts/account/extensions/AccountERC7579.sol";␊ + import {IERC1271} from "@openzeppelin/contracts/interfaces/IERC1271.sol";␊ + import {PackedUserOperation} from "@openzeppelin/contracts/interfaces/draft-IERC4337.sol";␊ + ␊ + contract MyAccount is Account, IERC1271, AccountERC7579 {␊ + // The following functions are overrides required by Solidity.␊ + ␊ + function _validateUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash)␊ + internal␊ + override(Account, AccountERC7579)␊ + returns (uint256)␊ + {␊ + return super._validateUserOp(userOp, userOpHash);␊ + }␊ + ␊ + function isValidSignature(bytes32 hash, bytes calldata signature)␊ + public␊ + view␊ + override(IERC1271, AccountERC7579)␊ + returns (bytes4)␊ + {␊ + return super.isValidSignature(hash, signature);␊ + }␊ + }␊ + ` + +## Account with ERC7579 with ERC7739 + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts ^5.0.0␊ + pragma solidity ^0.8.27;␊ + ␊ + import {Account} from "@openzeppelin/community-contracts/contracts/account/Account.sol";␊ + import {AccountERC7579} from "@openzeppelin/community-contracts/contracts/account/extensions/AccountERC7579.sol";␊ + import {EIP712} from "@openzeppelin/contracts/utils/cryptography/EIP712.sol";␊ + import {ERC7739} from "@openzeppelin/community-contracts/contracts/utils/cryptography/ERC7739.sol";␊ + import {PackedUserOperation} from "@openzeppelin/contracts/interfaces/draft-IERC4337.sol";␊ + ␊ + contract MyAccount is Account, EIP712, ERC7739, AccountERC7579 {␊ constructor() EIP712("MyAccount", "1") {}␊ ␊ function isValidSignature(bytes32 hash, bytes calldata signature)␊ @@ -269,7 +345,7 @@ Generated by [AVA](https://avajs.dev). import {ERC7739} from "@openzeppelin/community-contracts/contracts/utils/cryptography/ERC7739.sol";␊ import {PackedUserOperation} from "@openzeppelin/contracts/interfaces/draft-IERC4337.sol";␊ ␊ - contract MyAccount is Account, EIP712, AccountERC7579Hooked, ERC7739 {␊ + contract MyAccount is Account, EIP712, ERC7739, AccountERC7579Hooked {␊ constructor() EIP712("MyAccount", "1") {}␊ ␊ function isValidSignature(bytes32 hash, bytes calldata signature)␊ @@ -460,7 +536,113 @@ Generated by [AVA](https://avajs.dev). import {PackedUserOperation} from "@openzeppelin/contracts/interfaces/draft-IERC4337.sol";␊ import {SignerERC7702} from "@openzeppelin/community-contracts/contracts/utils/cryptography/SignerERC7702.sol";␊ ␊ - contract MyAccount is Account, EIP712, AccountERC7579, ERC7739, SignerERC7702 {␊ + contract MyAccount is Account, EIP712, ERC7739, AccountERC7579, SignerERC7702 {␊ + constructor() EIP712("MyAccount", "1") {}␊ + ␊ + function isValidSignature(bytes32 hash, bytes calldata signature)␊ + public␊ + view␊ + override(AccountERC7579, ERC7739)␊ + returns (bytes4)␊ + {␊ + // ERC-7739 can return the ERC-1271 magic value, 0xffffffff (invalid) or 0x77390001 (detection).␊ + // If the returned value is 0xffffffff, fallback to ERC-7579 validation.␊ + bytes4 erc7739magic = ERC7739.isValidSignature(hash, signature);␊ + return erc7739magic == bytes4(0xffffffff) ? AccountERC7579.isValidSignature(hash, signature) : erc7739magic;␊ + }␊ + ␊ + // The following functions are overrides required by Solidity.␊ + ␊ + function _validateUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash)␊ + internal␊ + override(Account, AccountERC7579)␊ + returns (uint256)␊ + {␊ + return super._validateUserOp(userOp, userOpHash);␊ + }␊ + ␊ + // IMPORTANT: Make sure SignerERC7702 is most derived than AccountERC7579␊ + // in the inheritance chain (i.e. contract ... is AccountERC7579, ..., SignerERC7702)␊ + // to ensure the correct order of function resolution.␊ + // AccountERC7579 returns false for \`_rawSignatureValidation\`␊ + function _rawSignatureValidation(bytes32 hash, bytes calldata signature)␊ + internal␊ + view␊ + override(SignerERC7702, AbstractSigner, AccountERC7579)␊ + returns (bool)␊ + {␊ + return super._rawSignatureValidation(hash, signature);␊ + }␊ + }␊ + ` + +## Account with SignerERC7702 with ERC7579 with ERC1271 + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts ^5.0.0␊ + pragma solidity ^0.8.27;␊ + ␊ + import {AbstractSigner} from "@openzeppelin/community-contracts/contracts/utils/cryptography/AbstractSigner.sol";␊ + import {Account} from "@openzeppelin/community-contracts/contracts/account/Account.sol";␊ + import {AccountERC7579} from "@openzeppelin/community-contracts/contracts/account/extensions/AccountERC7579.sol";␊ + import {IERC1271} from "@openzeppelin/contracts/interfaces/IERC1271.sol";␊ + import {PackedUserOperation} from "@openzeppelin/contracts/interfaces/draft-IERC4337.sol";␊ + import {SignerERC7702} from "@openzeppelin/community-contracts/contracts/utils/cryptography/SignerERC7702.sol";␊ + ␊ + contract MyAccount is Account, IERC1271, AccountERC7579, SignerERC7702 {␊ + // The following functions are overrides required by Solidity.␊ + ␊ + function _validateUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash)␊ + internal␊ + override(Account, AccountERC7579)␊ + returns (uint256)␊ + {␊ + return super._validateUserOp(userOp, userOpHash);␊ + }␊ + ␊ + function isValidSignature(bytes32 hash, bytes calldata signature)␊ + public␊ + view␊ + override(IERC1271, AccountERC7579)␊ + returns (bytes4)␊ + {␊ + return super.isValidSignature(hash, signature);␊ + }␊ + ␊ + // IMPORTANT: Make sure SignerERC7702 is most derived than AccountERC7579␊ + // in the inheritance chain (i.e. contract ... is AccountERC7579, ..., SignerERC7702)␊ + // to ensure the correct order of function resolution.␊ + // AccountERC7579 returns false for \`_rawSignatureValidation\`␊ + function _rawSignatureValidation(bytes32 hash, bytes calldata signature)␊ + internal␊ + view␊ + override(SignerERC7702, AbstractSigner, AccountERC7579)␊ + returns (bool)␊ + {␊ + return super._rawSignatureValidation(hash, signature);␊ + }␊ + }␊ + ` + +## Account with SignerERC7702 with ERC7579 with ERC7739 + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts ^5.0.0␊ + pragma solidity ^0.8.27;␊ + ␊ + import {AbstractSigner} from "@openzeppelin/community-contracts/contracts/utils/cryptography/AbstractSigner.sol";␊ + import {Account} from "@openzeppelin/community-contracts/contracts/account/Account.sol";␊ + import {AccountERC7579} from "@openzeppelin/community-contracts/contracts/account/extensions/AccountERC7579.sol";␊ + import {EIP712} from "@openzeppelin/contracts/utils/cryptography/EIP712.sol";␊ + import {ERC7739} from "@openzeppelin/community-contracts/contracts/utils/cryptography/ERC7739.sol";␊ + import {PackedUserOperation} from "@openzeppelin/contracts/interfaces/draft-IERC4337.sol";␊ + import {SignerERC7702} from "@openzeppelin/community-contracts/contracts/utils/cryptography/SignerERC7702.sol";␊ + ␊ + contract MyAccount is Account, EIP712, ERC7739, AccountERC7579, SignerERC7702 {␊ constructor() EIP712("MyAccount", "1") {}␊ ␊ function isValidSignature(bytes32 hash, bytes calldata signature)␊ @@ -517,7 +699,7 @@ Generated by [AVA](https://avajs.dev). import {PackedUserOperation} from "@openzeppelin/contracts/interfaces/draft-IERC4337.sol";␊ import {SignerERC7702} from "@openzeppelin/community-contracts/contracts/utils/cryptography/SignerERC7702.sol";␊ ␊ - contract MyAccount is Account, EIP712, AccountERC7579Hooked, ERC7739, SignerERC7702 {␊ + contract MyAccount is Account, EIP712, ERC7739, AccountERC7579Hooked, SignerERC7702 {␊ constructor() EIP712("MyAccount", "1") {}␊ ␊ function isValidSignature(bytes32 hash, bytes calldata signature)␊ @@ -757,7 +939,123 @@ Generated by [AVA](https://avajs.dev). import {PackedUserOperation} from "@openzeppelin/contracts/interfaces/draft-IERC4337.sol";␊ import {SignerECDSA} from "@openzeppelin/community-contracts/contracts/utils/cryptography/SignerECDSA.sol";␊ ␊ - contract MyAccount is Initializable, Account, EIP712, AccountERC7579, ERC7739, SignerECDSA {␊ + contract MyAccount is Initializable, Account, EIP712, ERC7739, AccountERC7579, SignerECDSA {␊ + constructor() EIP712("MyAccount", "1") {}␊ + ␊ + function isValidSignature(bytes32 hash, bytes calldata signature)␊ + public␊ + view␊ + override(AccountERC7579, ERC7739)␊ + returns (bytes4)␊ + {␊ + // ERC-7739 can return the ERC-1271 magic value, 0xffffffff (invalid) or 0x77390001 (detection).␊ + // If the returned value is 0xffffffff, fallback to ERC-7579 validation.␊ + bytes4 erc7739magic = ERC7739.isValidSignature(hash, signature);␊ + return erc7739magic == bytes4(0xffffffff) ? AccountERC7579.isValidSignature(hash, signature) : erc7739magic;␊ + }␊ + ␊ + function initializeECDSA(address signer) public initializer {␊ + _setSigner(signer);␊ + }␊ + ␊ + // The following functions are overrides required by Solidity.␊ + ␊ + function _validateUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash)␊ + internal␊ + override(Account, AccountERC7579)␊ + returns (uint256)␊ + {␊ + return super._validateUserOp(userOp, userOpHash);␊ + }␊ + ␊ + // IMPORTANT: Make sure SignerECDSA is most derived than AccountERC7579␊ + // in the inheritance chain (i.e. contract ... is AccountERC7579, ..., SignerECDSA)␊ + // to ensure the correct order of function resolution.␊ + // AccountERC7579 returns false for \`_rawSignatureValidation\`␊ + function _rawSignatureValidation(bytes32 hash, bytes calldata signature)␊ + internal␊ + view␊ + override(SignerECDSA, AbstractSigner, AccountERC7579)␊ + returns (bool)␊ + {␊ + return super._rawSignatureValidation(hash, signature);␊ + }␊ + }␊ + ` + +## Account with SignerECDSA with ERC7579 with ERC1271 + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts ^5.0.0␊ + pragma solidity ^0.8.27;␊ + ␊ + import {AbstractSigner} from "@openzeppelin/community-contracts/contracts/utils/cryptography/AbstractSigner.sol";␊ + import {Account} from "@openzeppelin/community-contracts/contracts/account/Account.sol";␊ + import {AccountERC7579} from "@openzeppelin/community-contracts/contracts/account/extensions/AccountERC7579.sol";␊ + import {IERC1271} from "@openzeppelin/contracts/interfaces/IERC1271.sol";␊ + import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol";␊ + import {PackedUserOperation} from "@openzeppelin/contracts/interfaces/draft-IERC4337.sol";␊ + import {SignerECDSA} from "@openzeppelin/community-contracts/contracts/utils/cryptography/SignerECDSA.sol";␊ + ␊ + contract MyAccount is Initializable, Account, IERC1271, AccountERC7579, SignerECDSA {␊ + function initializeECDSA(address signer) public initializer {␊ + _setSigner(signer);␊ + }␊ + ␊ + // The following functions are overrides required by Solidity.␊ + ␊ + function _validateUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash)␊ + internal␊ + override(Account, AccountERC7579)␊ + returns (uint256)␊ + {␊ + return super._validateUserOp(userOp, userOpHash);␊ + }␊ + ␊ + function isValidSignature(bytes32 hash, bytes calldata signature)␊ + public␊ + view␊ + override(IERC1271, AccountERC7579)␊ + returns (bytes4)␊ + {␊ + return super.isValidSignature(hash, signature);␊ + }␊ + ␊ + // IMPORTANT: Make sure SignerECDSA is most derived than AccountERC7579␊ + // in the inheritance chain (i.e. contract ... is AccountERC7579, ..., SignerECDSA)␊ + // to ensure the correct order of function resolution.␊ + // AccountERC7579 returns false for \`_rawSignatureValidation\`␊ + function _rawSignatureValidation(bytes32 hash, bytes calldata signature)␊ + internal␊ + view␊ + override(SignerECDSA, AbstractSigner, AccountERC7579)␊ + returns (bool)␊ + {␊ + return super._rawSignatureValidation(hash, signature);␊ + }␊ + }␊ + ` + +## Account with SignerECDSA with ERC7579 with ERC7739 + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts ^5.0.0␊ + pragma solidity ^0.8.27;␊ + ␊ + import {AbstractSigner} from "@openzeppelin/community-contracts/contracts/utils/cryptography/AbstractSigner.sol";␊ + import {Account} from "@openzeppelin/community-contracts/contracts/account/Account.sol";␊ + import {AccountERC7579} from "@openzeppelin/community-contracts/contracts/account/extensions/AccountERC7579.sol";␊ + import {EIP712} from "@openzeppelin/contracts/utils/cryptography/EIP712.sol";␊ + import {ERC7739} from "@openzeppelin/community-contracts/contracts/utils/cryptography/ERC7739.sol";␊ + import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol";␊ + import {PackedUserOperation} from "@openzeppelin/contracts/interfaces/draft-IERC4337.sol";␊ + import {SignerECDSA} from "@openzeppelin/community-contracts/contracts/utils/cryptography/SignerECDSA.sol";␊ + ␊ + contract MyAccount is Initializable, Account, EIP712, ERC7739, AccountERC7579, SignerECDSA {␊ constructor() EIP712("MyAccount", "1") {}␊ ␊ function isValidSignature(bytes32 hash, bytes calldata signature)␊ @@ -819,7 +1117,7 @@ Generated by [AVA](https://avajs.dev). import {PackedUserOperation} from "@openzeppelin/contracts/interfaces/draft-IERC4337.sol";␊ import {SignerECDSA} from "@openzeppelin/community-contracts/contracts/utils/cryptography/SignerECDSA.sol";␊ ␊ - contract MyAccount is Initializable, Account, EIP712, AccountERC7579Hooked, ERC7739, SignerECDSA {␊ + contract MyAccount is Initializable, Account, EIP712, ERC7739, AccountERC7579Hooked, SignerECDSA {␊ constructor() EIP712("MyAccount", "1") {}␊ ␊ function isValidSignature(bytes32 hash, bytes calldata signature)␊ @@ -1063,7 +1361,123 @@ Generated by [AVA](https://avajs.dev). import {PackedUserOperation} from "@openzeppelin/contracts/interfaces/draft-IERC4337.sol";␊ import {SignerP256} from "@openzeppelin/community-contracts/contracts/utils/cryptography/SignerP256.sol";␊ ␊ - contract MyAccount is Initializable, Account, EIP712, AccountERC7579, ERC7739, SignerP256 {␊ + contract MyAccount is Initializable, Account, EIP712, ERC7739, AccountERC7579, SignerP256 {␊ + constructor() EIP712("MyAccount", "1") {}␊ + ␊ + function isValidSignature(bytes32 hash, bytes calldata signature)␊ + public␊ + view␊ + override(AccountERC7579, ERC7739)␊ + returns (bytes4)␊ + {␊ + // ERC-7739 can return the ERC-1271 magic value, 0xffffffff (invalid) or 0x77390001 (detection).␊ + // If the returned value is 0xffffffff, fallback to ERC-7579 validation.␊ + bytes4 erc7739magic = ERC7739.isValidSignature(hash, signature);␊ + return erc7739magic == bytes4(0xffffffff) ? AccountERC7579.isValidSignature(hash, signature) : erc7739magic;␊ + }␊ + ␊ + function initializeP256(bytes32 qx, bytes32 qy) public initializer {␊ + _setSigner(qx, qy);␊ + }␊ + ␊ + // The following functions are overrides required by Solidity.␊ + ␊ + function _validateUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash)␊ + internal␊ + override(Account, AccountERC7579)␊ + returns (uint256)␊ + {␊ + return super._validateUserOp(userOp, userOpHash);␊ + }␊ + ␊ + // IMPORTANT: Make sure SignerP256 is most derived than AccountERC7579␊ + // in the inheritance chain (i.e. contract ... is AccountERC7579, ..., SignerP256)␊ + // to ensure the correct order of function resolution.␊ + // AccountERC7579 returns false for \`_rawSignatureValidation\`␊ + function _rawSignatureValidation(bytes32 hash, bytes calldata signature)␊ + internal␊ + view␊ + override(SignerP256, AbstractSigner, AccountERC7579)␊ + returns (bool)␊ + {␊ + return super._rawSignatureValidation(hash, signature);␊ + }␊ + }␊ + ` + +## Account with SignerP256 with ERC7579 with ERC1271 + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts ^5.0.0␊ + pragma solidity ^0.8.27;␊ + ␊ + import {AbstractSigner} from "@openzeppelin/community-contracts/contracts/utils/cryptography/AbstractSigner.sol";␊ + import {Account} from "@openzeppelin/community-contracts/contracts/account/Account.sol";␊ + import {AccountERC7579} from "@openzeppelin/community-contracts/contracts/account/extensions/AccountERC7579.sol";␊ + import {IERC1271} from "@openzeppelin/contracts/interfaces/IERC1271.sol";␊ + import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol";␊ + import {PackedUserOperation} from "@openzeppelin/contracts/interfaces/draft-IERC4337.sol";␊ + import {SignerP256} from "@openzeppelin/community-contracts/contracts/utils/cryptography/SignerP256.sol";␊ + ␊ + contract MyAccount is Initializable, Account, IERC1271, AccountERC7579, SignerP256 {␊ + function initializeP256(bytes32 qx, bytes32 qy) public initializer {␊ + _setSigner(qx, qy);␊ + }␊ + ␊ + // The following functions are overrides required by Solidity.␊ + ␊ + function _validateUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash)␊ + internal␊ + override(Account, AccountERC7579)␊ + returns (uint256)␊ + {␊ + return super._validateUserOp(userOp, userOpHash);␊ + }␊ + ␊ + function isValidSignature(bytes32 hash, bytes calldata signature)␊ + public␊ + view␊ + override(IERC1271, AccountERC7579)␊ + returns (bytes4)␊ + {␊ + return super.isValidSignature(hash, signature);␊ + }␊ + ␊ + // IMPORTANT: Make sure SignerP256 is most derived than AccountERC7579␊ + // in the inheritance chain (i.e. contract ... is AccountERC7579, ..., SignerP256)␊ + // to ensure the correct order of function resolution.␊ + // AccountERC7579 returns false for \`_rawSignatureValidation\`␊ + function _rawSignatureValidation(bytes32 hash, bytes calldata signature)␊ + internal␊ + view␊ + override(SignerP256, AbstractSigner, AccountERC7579)␊ + returns (bool)␊ + {␊ + return super._rawSignatureValidation(hash, signature);␊ + }␊ + }␊ + ` + +## Account with SignerP256 with ERC7579 with ERC7739 + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts ^5.0.0␊ + pragma solidity ^0.8.27;␊ + ␊ + import {AbstractSigner} from "@openzeppelin/community-contracts/contracts/utils/cryptography/AbstractSigner.sol";␊ + import {Account} from "@openzeppelin/community-contracts/contracts/account/Account.sol";␊ + import {AccountERC7579} from "@openzeppelin/community-contracts/contracts/account/extensions/AccountERC7579.sol";␊ + import {EIP712} from "@openzeppelin/contracts/utils/cryptography/EIP712.sol";␊ + import {ERC7739} from "@openzeppelin/community-contracts/contracts/utils/cryptography/ERC7739.sol";␊ + import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol";␊ + import {PackedUserOperation} from "@openzeppelin/contracts/interfaces/draft-IERC4337.sol";␊ + import {SignerP256} from "@openzeppelin/community-contracts/contracts/utils/cryptography/SignerP256.sol";␊ + ␊ + contract MyAccount is Initializable, Account, EIP712, ERC7739, AccountERC7579, SignerP256 {␊ constructor() EIP712("MyAccount", "1") {}␊ ␊ function isValidSignature(bytes32 hash, bytes calldata signature)␊ @@ -1125,7 +1539,7 @@ Generated by [AVA](https://avajs.dev). import {PackedUserOperation} from "@openzeppelin/contracts/interfaces/draft-IERC4337.sol";␊ import {SignerP256} from "@openzeppelin/community-contracts/contracts/utils/cryptography/SignerP256.sol";␊ ␊ - contract MyAccount is Initializable, Account, EIP712, AccountERC7579Hooked, ERC7739, SignerP256 {␊ + contract MyAccount is Initializable, Account, EIP712, ERC7739, AccountERC7579Hooked, SignerP256 {␊ constructor() EIP712("MyAccount", "1") {}␊ ␊ function isValidSignature(bytes32 hash, bytes calldata signature)␊ @@ -1369,7 +1783,123 @@ Generated by [AVA](https://avajs.dev). import {PackedUserOperation} from "@openzeppelin/contracts/interfaces/draft-IERC4337.sol";␊ import {SignerRSA} from "@openzeppelin/community-contracts/contracts/utils/cryptography/SignerRSA.sol";␊ ␊ - contract MyAccount is Initializable, Account, EIP712, AccountERC7579, ERC7739, SignerRSA {␊ + contract MyAccount is Initializable, Account, EIP712, ERC7739, AccountERC7579, SignerRSA {␊ + constructor() EIP712("MyAccount", "1") {}␊ + ␊ + function isValidSignature(bytes32 hash, bytes calldata signature)␊ + public␊ + view␊ + override(AccountERC7579, ERC7739)␊ + returns (bytes4)␊ + {␊ + // ERC-7739 can return the ERC-1271 magic value, 0xffffffff (invalid) or 0x77390001 (detection).␊ + // If the returned value is 0xffffffff, fallback to ERC-7579 validation.␊ + bytes4 erc7739magic = ERC7739.isValidSignature(hash, signature);␊ + return erc7739magic == bytes4(0xffffffff) ? AccountERC7579.isValidSignature(hash, signature) : erc7739magic;␊ + }␊ + ␊ + function initializeRSA(bytes memory e, bytes memory n) public initializer {␊ + _setSigner(e, n);␊ + }␊ + ␊ + // The following functions are overrides required by Solidity.␊ + ␊ + function _validateUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash)␊ + internal␊ + override(Account, AccountERC7579)␊ + returns (uint256)␊ + {␊ + return super._validateUserOp(userOp, userOpHash);␊ + }␊ + ␊ + // IMPORTANT: Make sure SignerRSA is most derived than AccountERC7579␊ + // in the inheritance chain (i.e. contract ... is AccountERC7579, ..., SignerRSA)␊ + // to ensure the correct order of function resolution.␊ + // AccountERC7579 returns false for \`_rawSignatureValidation\`␊ + function _rawSignatureValidation(bytes32 hash, bytes calldata signature)␊ + internal␊ + view␊ + override(SignerRSA, AbstractSigner, AccountERC7579)␊ + returns (bool)␊ + {␊ + return super._rawSignatureValidation(hash, signature);␊ + }␊ + }␊ + ` + +## Account with SignerRSA with ERC7579 with ERC1271 + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts ^5.0.0␊ + pragma solidity ^0.8.27;␊ + ␊ + import {AbstractSigner} from "@openzeppelin/community-contracts/contracts/utils/cryptography/AbstractSigner.sol";␊ + import {Account} from "@openzeppelin/community-contracts/contracts/account/Account.sol";␊ + import {AccountERC7579} from "@openzeppelin/community-contracts/contracts/account/extensions/AccountERC7579.sol";␊ + import {IERC1271} from "@openzeppelin/contracts/interfaces/IERC1271.sol";␊ + import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol";␊ + import {PackedUserOperation} from "@openzeppelin/contracts/interfaces/draft-IERC4337.sol";␊ + import {SignerRSA} from "@openzeppelin/community-contracts/contracts/utils/cryptography/SignerRSA.sol";␊ + ␊ + contract MyAccount is Initializable, Account, IERC1271, AccountERC7579, SignerRSA {␊ + function initializeRSA(bytes memory e, bytes memory n) public initializer {␊ + _setSigner(e, n);␊ + }␊ + ␊ + // The following functions are overrides required by Solidity.␊ + ␊ + function _validateUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash)␊ + internal␊ + override(Account, AccountERC7579)␊ + returns (uint256)␊ + {␊ + return super._validateUserOp(userOp, userOpHash);␊ + }␊ + ␊ + function isValidSignature(bytes32 hash, bytes calldata signature)␊ + public␊ + view␊ + override(IERC1271, AccountERC7579)␊ + returns (bytes4)␊ + {␊ + return super.isValidSignature(hash, signature);␊ + }␊ + ␊ + // IMPORTANT: Make sure SignerRSA is most derived than AccountERC7579␊ + // in the inheritance chain (i.e. contract ... is AccountERC7579, ..., SignerRSA)␊ + // to ensure the correct order of function resolution.␊ + // AccountERC7579 returns false for \`_rawSignatureValidation\`␊ + function _rawSignatureValidation(bytes32 hash, bytes calldata signature)␊ + internal␊ + view␊ + override(SignerRSA, AbstractSigner, AccountERC7579)␊ + returns (bool)␊ + {␊ + return super._rawSignatureValidation(hash, signature);␊ + }␊ + }␊ + ` + +## Account with SignerRSA with ERC7579 with ERC7739 + +> Snapshot 1 + + `// SPDX-License-Identifier: MIT␊ + // Compatible with OpenZeppelin Contracts ^5.0.0␊ + pragma solidity ^0.8.27;␊ + ␊ + import {AbstractSigner} from "@openzeppelin/community-contracts/contracts/utils/cryptography/AbstractSigner.sol";␊ + import {Account} from "@openzeppelin/community-contracts/contracts/account/Account.sol";␊ + import {AccountERC7579} from "@openzeppelin/community-contracts/contracts/account/extensions/AccountERC7579.sol";␊ + import {EIP712} from "@openzeppelin/contracts/utils/cryptography/EIP712.sol";␊ + import {ERC7739} from "@openzeppelin/community-contracts/contracts/utils/cryptography/ERC7739.sol";␊ + import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol";␊ + import {PackedUserOperation} from "@openzeppelin/contracts/interfaces/draft-IERC4337.sol";␊ + import {SignerRSA} from "@openzeppelin/community-contracts/contracts/utils/cryptography/SignerRSA.sol";␊ + ␊ + contract MyAccount is Initializable, Account, EIP712, ERC7739, AccountERC7579, SignerRSA {␊ constructor() EIP712("MyAccount", "1") {}␊ ␊ function isValidSignature(bytes32 hash, bytes calldata signature)␊ @@ -1431,7 +1961,7 @@ Generated by [AVA](https://avajs.dev). import {PackedUserOperation} from "@openzeppelin/contracts/interfaces/draft-IERC4337.sol";␊ import {SignerRSA} from "@openzeppelin/community-contracts/contracts/utils/cryptography/SignerRSA.sol";␊ ␊ - contract MyAccount is Initializable, Account, EIP712, AccountERC7579Hooked, ERC7739, SignerRSA {␊ + contract MyAccount is Initializable, Account, EIP712, ERC7739, AccountERC7579Hooked, SignerRSA {␊ constructor() EIP712("MyAccount", "1") {}␊ ␊ function isValidSignature(bytes32 hash, bytes calldata signature)␊ diff --git a/packages/core/solidity/src/account.test.ts.snap b/packages/core/solidity/src/account.test.ts.snap index c03d953fc..84f2901cc 100644 Binary files a/packages/core/solidity/src/account.test.ts.snap and b/packages/core/solidity/src/account.test.ts.snap differ diff --git a/packages/core/solidity/src/account.ts b/packages/core/solidity/src/account.ts index fbd292d69..11eea122e 100644 --- a/packages/core/solidity/src/account.ts +++ b/packages/core/solidity/src/account.ts @@ -12,7 +12,7 @@ export const defaults: Required = { signatureValidation: 'ERC7739', ERC721Holder: true, ERC1155Holder: true, - signer: false, + signer: 'ECDSA', batchedExecution: false, ERC7579Modules: false, } as const; @@ -83,8 +83,8 @@ function addParents(c: ContractBuilder, opts: AccountOptions): void { if (opts.signatureValidation === 'ERC7739') addEIP712(c, opts); // Extensions - addERC7579Modules(c, opts); addSignatureValidation(c, opts); + addERC7579Modules(c, opts); addSigner(c, opts.signer ?? false); addBatchedExecution(c, opts); addERC721Holder(c, opts); diff --git a/packages/ui/src/solidity/AccountControls.svelte b/packages/ui/src/solidity/AccountControls.svelte index f92c34a21..640f82972 100644 --- a/packages/ui/src/solidity/AccountControls.svelte +++ b/packages/ui/src/solidity/AccountControls.svelte @@ -72,8 +72,8 @@ Account Bound Enhances signature security by using a defensive rehashing scheme that prevents signature replay attacks across - multiple smart accounts owned by the same EOA. This preserves the readability of signed contents while ensuring - each signature is uniquely bound to a specific account and chain. + multiple smart accounts owned by the same private key. This preserves the readability of signed contents while + ensuring each signature is uniquely bound to a specific account and chain.