From a8388192b15812c89ead767b04e0f7517b1fda4d Mon Sep 17 00:00:00 2001 From: howydev <132113803+howydev@users.noreply.github.com> Date: Sat, 20 Apr 2024 15:56:27 -0400 Subject: [PATCH 1/6] chore: bump 4337 to v0.7 --- lib/account-abstraction | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/account-abstraction b/lib/account-abstraction index 187613b0..7af70c89 160000 --- a/lib/account-abstraction +++ b/lib/account-abstraction @@ -1 +1 @@ -Subproject commit 187613b0172c3a21cf3496e12cdfa24af04fb510 +Subproject commit 7af70c8993a6f42973f520ae0752386a5032abe7 From e838c93ed419c233d5ef6c232bd236b22868c35f Mon Sep 17 00:00:00 2001 From: howydev <132113803+howydev@users.noreply.github.com> Date: Sat, 20 Apr 2024 16:01:44 -0400 Subject: [PATCH 2/6] chore: update UO to PackedUO --- src/account/UpgradeableModularAccount.sol | 6 ++-- src/interfaces/IPlugin.sol | 6 ++-- src/plugins/BasePlugin.sol | 6 ++-- src/plugins/owner/SingleOwnerPlugin.sol | 4 +-- .../plugins/ModularSessionKeyPlugin.sol | 4 +-- .../plugins/interfaces/ISessionKeyPlugin.sol | 2 +- .../interfaces/ITokenSessionKeyPlugin.sol | 2 +- standard/ERCs/erc-6900.md | 4 +-- test/account/UpgradeableModularAccount.t.sol | 28 +++++++++---------- test/account/ValidationIntersection.t.sol | 22 +++++++-------- test/comparison/CompareSimpleAccount.t.sol | 20 ++++++------- test/mocks/MSCAFactoryFixture.sol | 2 +- test/mocks/plugins/ComprehensivePlugin.sol | 6 ++-- test/mocks/plugins/ValidationPluginMocks.sol | 6 ++-- test/plugin/SingleOwnerPlugin.t.sol | 4 +-- .../plugins/ModularSessionKeyPlugin.t.sol | 14 +++++----- 16 files changed, 68 insertions(+), 68 deletions(-) diff --git a/src/account/UpgradeableModularAccount.sol b/src/account/UpgradeableModularAccount.sol index 1a7c0ac3..81496a2a 100644 --- a/src/account/UpgradeableModularAccount.sol +++ b/src/account/UpgradeableModularAccount.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.25; import {BaseAccount} from "@eth-infinitism/account-abstraction/core/BaseAccount.sol"; import {IEntryPoint} from "@eth-infinitism/account-abstraction/interfaces/IEntryPoint.sol"; -import {UserOperation} from "@eth-infinitism/account-abstraction/interfaces/UserOperation.sol"; +import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interfaces/PackedUserOperation.sol"; import {UUPSUpgradeable} from "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol"; import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import {EnumerableMap} from "@openzeppelin/contracts/utils/structs/EnumerableMap.sol"; @@ -317,7 +317,7 @@ contract UpgradeableModularAccount is // INTERNAL FUNCTIONS // Parent function validateUserOp enforces that this call can only be made by the EntryPoint - function _validateSignature(UserOperation calldata userOp, bytes32 userOpHash) + function _validateSignature(PackedUserOperation calldata userOp, bytes32 userOpHash) internal virtual override @@ -337,7 +337,7 @@ contract UpgradeableModularAccount is function _doUserOpValidation( bytes4 selector, FunctionReference userOpValidationFunction, - UserOperation calldata userOp, + PackedUserOperation calldata userOp, bytes32 userOpHash ) internal returns (uint256 validationData) { if (userOpValidationFunction.isEmpty()) { diff --git a/src/interfaces/IPlugin.sol b/src/interfaces/IPlugin.sol index 5c4702d2..dd4b1f80 100644 --- a/src/interfaces/IPlugin.sol +++ b/src/interfaces/IPlugin.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: CC0-1.0 pragma solidity ^0.8.25; -import {UserOperation} from "@eth-infinitism/account-abstraction/interfaces/UserOperation.sol"; +import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interfaces/PackedUserOperation.sol"; // Forge formatter will displace the first comment for the enum field out of the enum itself, // so annotating here to prevent that. @@ -116,7 +116,7 @@ interface IPlugin { /// @param userOp The user operation. /// @param userOpHash The user operation hash. /// @return Packed validation data for validAfter (6 bytes), validUntil (6 bytes), and authorizer (20 bytes). - function preUserOpValidationHook(uint8 functionId, UserOperation calldata userOp, bytes32 userOpHash) + function preUserOpValidationHook(uint8 functionId, PackedUserOperation calldata userOp, bytes32 userOpHash) external returns (uint256); @@ -126,7 +126,7 @@ interface IPlugin { /// @param userOp The user operation. /// @param userOpHash The user operation hash. /// @return Packed validation data for validAfter (6 bytes), validUntil (6 bytes), and authorizer (20 bytes). - function userOpValidationFunction(uint8 functionId, UserOperation calldata userOp, bytes32 userOpHash) + function userOpValidationFunction(uint8 functionId, PackedUserOperation calldata userOp, bytes32 userOpHash) external returns (uint256); diff --git a/src/plugins/BasePlugin.sol b/src/plugins/BasePlugin.sol index 5a89b982..44145286 100644 --- a/src/plugins/BasePlugin.sol +++ b/src/plugins/BasePlugin.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.25; -import {UserOperation} from "@eth-infinitism/account-abstraction/interfaces/UserOperation.sol"; +import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interfaces/PackedUserOperation.sol"; import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; import {IPlugin, PluginManifest, PluginMetadata} from "../interfaces/IPlugin.sol"; @@ -38,7 +38,7 @@ abstract contract BasePlugin is ERC165, IPlugin { /// @param userOp The user operation. /// @param userOpHash The user operation hash. /// @return Packed validation data for validAfter (6 bytes), validUntil (6 bytes), and authorizer (20 bytes). - function preUserOpValidationHook(uint8 functionId, UserOperation calldata userOp, bytes32 userOpHash) + function preUserOpValidationHook(uint8 functionId, PackedUserOperation calldata userOp, bytes32 userOpHash) external virtual returns (uint256) @@ -53,7 +53,7 @@ abstract contract BasePlugin is ERC165, IPlugin { /// @param userOp The user operation. /// @param userOpHash The user operation hash. /// @return Packed validation data for validAfter (6 bytes), validUntil (6 bytes), and authorizer (20 bytes). - function userOpValidationFunction(uint8 functionId, UserOperation calldata userOp, bytes32 userOpHash) + function userOpValidationFunction(uint8 functionId, PackedUserOperation calldata userOp, bytes32 userOpHash) external virtual returns (uint256) diff --git a/src/plugins/owner/SingleOwnerPlugin.sol b/src/plugins/owner/SingleOwnerPlugin.sol index 5e3b432a..bfff2aa4 100644 --- a/src/plugins/owner/SingleOwnerPlugin.sol +++ b/src/plugins/owner/SingleOwnerPlugin.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.25; import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import {IERC1271} from "@openzeppelin/contracts/interfaces/IERC1271.sol"; import {SignatureChecker} from "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol"; -import {UserOperation} from "@eth-infinitism/account-abstraction/interfaces/UserOperation.sol"; +import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interfaces/PackedUserOperation.sol"; import {UUPSUpgradeable} from "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol"; import {IPluginManager} from "../../interfaces/IPluginManager.sol"; @@ -91,7 +91,7 @@ contract SingleOwnerPlugin is BasePlugin, ISingleOwnerPlugin, IERC1271 { } /// @inheritdoc BasePlugin - function userOpValidationFunction(uint8 functionId, UserOperation calldata userOp, bytes32 userOpHash) + function userOpValidationFunction(uint8 functionId, PackedUserOperation calldata userOp, bytes32 userOpHash) external view override diff --git a/src/samples/plugins/ModularSessionKeyPlugin.sol b/src/samples/plugins/ModularSessionKeyPlugin.sol index ceed7108..53b4c0eb 100644 --- a/src/samples/plugins/ModularSessionKeyPlugin.sol +++ b/src/samples/plugins/ModularSessionKeyPlugin.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.25; // import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; // import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; -// import {UserOperation} from "@eth-infinitism/account-abstraction/interfaces/UserOperation.sol"; +// import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interfaces/PackedUserOperation.sol"; // import {UpgradeableModularAccount} from "../../account/UpgradeableModularAccount.sol"; // import { // ManifestFunction, @@ -188,7 +188,7 @@ pragma solidity ^0.8.25; // } // /// @inheritdoc BasePlugin -// function userOpValidationFunction(uint8 functionId, UserOperation calldata userOp, bytes32 userOpHash) +// function userOpValidationFunction(uint8 functionId, PackedUserOperation calldata userOp, bytes32 userOpHash) // external // view // override diff --git a/src/samples/plugins/interfaces/ISessionKeyPlugin.sol b/src/samples/plugins/interfaces/ISessionKeyPlugin.sol index 99d94456..fd1b9bd0 100644 --- a/src/samples/plugins/interfaces/ISessionKeyPlugin.sol +++ b/src/samples/plugins/interfaces/ISessionKeyPlugin.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.25; -// import {UserOperation} from "@eth-infinitism/account-abstraction/interfaces/UserOperation.sol"; +// import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interfaces/PackedUserOperation.sol"; // interface IModularSessionKeyPlugin { // enum FunctionId { diff --git a/src/samples/plugins/interfaces/ITokenSessionKeyPlugin.sol b/src/samples/plugins/interfaces/ITokenSessionKeyPlugin.sol index 09a3bf84..2de98c0a 100644 --- a/src/samples/plugins/interfaces/ITokenSessionKeyPlugin.sol +++ b/src/samples/plugins/interfaces/ITokenSessionKeyPlugin.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.25; -// import {UserOperation} from "@eth-infinitism/account-abstraction/interfaces/UserOperation.sol"; +// import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interfaces/PackedUserOperation.sol"; // interface ITokenSessionKeyPlugin { // error NotAuthorized(); diff --git a/standard/ERCs/erc-6900.md b/standard/ERCs/erc-6900.md index ce775c15..35f46e29 100644 --- a/standard/ERCs/erc-6900.md +++ b/standard/ERCs/erc-6900.md @@ -276,7 +276,7 @@ interface IPlugin { /// @param userOp The user operation. /// @param userOpHash The user operation hash. /// @return Packed validation data for validAfter (6 bytes), validUntil (6 bytes), and authorizer (20 bytes). - function preUserOpValidationHook(uint8 functionId, UserOperation memory userOp, bytes32 userOpHash) external returns (uint256); + function preUserOpValidationHook(uint8 functionId, PackedUserOperation memory userOp, bytes32 userOpHash) external returns (uint256); /// @notice Run the user operation validationFunction specified by the `functionId`. /// @param functionId An identifier that routes the call to different internal implementations, should there be @@ -284,7 +284,7 @@ interface IPlugin { /// @param userOp The user operation. /// @param userOpHash The user operation hash. /// @return Packed validation data for validAfter (6 bytes), validUntil (6 bytes), and authorizer (20 bytes). - function userOpValidationFunction(uint8 functionId, UserOperation calldata userOp, bytes32 userOpHash) + function userOpValidationFunction(uint8 functionId, PackedUserOperation calldata userOp, bytes32 userOpHash) external returns (uint256); diff --git a/test/account/UpgradeableModularAccount.t.sol b/test/account/UpgradeableModularAccount.t.sol index 486f283b..6d4ebeeb 100644 --- a/test/account/UpgradeableModularAccount.t.sol +++ b/test/account/UpgradeableModularAccount.t.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.19; import {console} from "forge-std/Test.sol"; import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; -import {UserOperation} from "@eth-infinitism/account-abstraction/interfaces/UserOperation.sol"; +import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interfaces/PackedUserOperation.sol"; import {PluginManagerInternals} from "../../src/account/PluginManagerInternals.sol"; import {UpgradeableModularAccount} from "../../src/account/UpgradeableModularAccount.sol"; @@ -62,7 +62,7 @@ contract UpgradeableModularAccountTest is AccountTestBase { } function test_postDeploy_ethSend() public { - UserOperation memory userOp = UserOperation({ + PackedUserOperation memory userOp = PackedUserOperation({ sender: address(account1), nonce: 0, initCode: "", @@ -81,7 +81,7 @@ contract UpgradeableModularAccountTest is AccountTestBase { (uint8 v, bytes32 r, bytes32 s) = vm.sign(owner1Key, userOpHash.toEthSignedMessageHash()); userOp.signature = abi.encodePacked(r, s, v); - UserOperation[] memory userOps = new UserOperation[](1); + PackedUserOperation[] memory userOps = new PackedUserOperation[](1); userOps[0] = userOp; entryPoint.handleOps(userOps, beneficiary); @@ -90,7 +90,7 @@ contract UpgradeableModularAccountTest is AccountTestBase { } function test_basicUserOp_withInitCode() public { - UserOperation memory userOp = UserOperation({ + PackedUserOperation memory userOp = PackedUserOperation({ sender: address(account2), nonce: 0, initCode: abi.encodePacked(address(factory), abi.encodeCall(factory.createAccount, (owner2, 0))), @@ -109,7 +109,7 @@ contract UpgradeableModularAccountTest is AccountTestBase { (uint8 v, bytes32 r, bytes32 s) = vm.sign(owner2Key, userOpHash.toEthSignedMessageHash()); userOp.signature = abi.encodePacked(r, s, v); - UserOperation[] memory userOps = new UserOperation[](1); + PackedUserOperation[] memory userOps = new PackedUserOperation[](1); userOps[0] = userOp; entryPoint.handleOps(userOps, beneficiary); @@ -118,7 +118,7 @@ contract UpgradeableModularAccountTest is AccountTestBase { function test_standardExecuteEthSend_withInitcode() public { address payable recipient = payable(makeAddr("recipient")); - UserOperation memory userOp = UserOperation({ + PackedUserOperation memory userOp = PackedUserOperation({ sender: address(account2), nonce: 0, initCode: abi.encodePacked(address(factory), abi.encodeCall(factory.createAccount, (owner2, 0))), @@ -137,7 +137,7 @@ contract UpgradeableModularAccountTest is AccountTestBase { (uint8 v, bytes32 r, bytes32 s) = vm.sign(owner2Key, userOpHash.toEthSignedMessageHash()); userOp.signature = abi.encodePacked(r, s, v); - UserOperation[] memory userOps = new UserOperation[](1); + PackedUserOperation[] memory userOps = new PackedUserOperation[](1); userOps[0] = userOp; entryPoint.handleOps(userOps, beneficiary); @@ -146,7 +146,7 @@ contract UpgradeableModularAccountTest is AccountTestBase { } function test_debug_upgradeableModularAccount_storageAccesses() public { - UserOperation memory userOp = UserOperation({ + PackedUserOperation memory userOp = PackedUserOperation({ sender: address(account1), nonce: 0, initCode: "", @@ -165,7 +165,7 @@ contract UpgradeableModularAccountTest is AccountTestBase { (uint8 v, bytes32 r, bytes32 s) = vm.sign(owner1Key, userOpHash.toEthSignedMessageHash()); userOp.signature = abi.encodePacked(r, s, v); - UserOperation[] memory userOps = new UserOperation[](1); + PackedUserOperation[] memory userOps = new PackedUserOperation[](1); userOps[0] = userOp; vm.record(); @@ -174,13 +174,13 @@ contract UpgradeableModularAccountTest is AccountTestBase { } function test_contractInteraction() public { - UserOperation memory userOp = UserOperation({ + PackedUserOperation memory userOp = PackedUserOperation({ sender: address(account1), nonce: 0, initCode: "", callData: abi.encodeCall( UpgradeableModularAccount.execute, (address(counter), 0, abi.encodeCall(counter.increment, ())) - ), + ), callGasLimit: CALL_GAS_LIMIT, verificationGasLimit: VERIFICATION_GAS_LIMIT, preVerificationGas: 0, @@ -195,7 +195,7 @@ contract UpgradeableModularAccountTest is AccountTestBase { (uint8 v, bytes32 r, bytes32 s) = vm.sign(owner1Key, userOpHash.toEthSignedMessageHash()); userOp.signature = abi.encodePacked(r, s, v); - UserOperation[] memory userOps = new UserOperation[](1); + PackedUserOperation[] memory userOps = new PackedUserOperation[](1); userOps[0] = userOp; entryPoint.handleOps(userOps, beneficiary); @@ -209,7 +209,7 @@ contract UpgradeableModularAccountTest is AccountTestBase { calls[0] = Call({target: ethRecipient, value: 1 wei, data: ""}); calls[1] = Call({target: address(counter), value: 0, data: abi.encodeCall(counter.increment, ())}); - UserOperation memory userOp = UserOperation({ + PackedUserOperation memory userOp = PackedUserOperation({ sender: address(account1), nonce: 0, initCode: "", @@ -228,7 +228,7 @@ contract UpgradeableModularAccountTest is AccountTestBase { (uint8 v, bytes32 r, bytes32 s) = vm.sign(owner1Key, userOpHash.toEthSignedMessageHash()); userOp.signature = abi.encodePacked(r, s, v); - UserOperation[] memory userOps = new UserOperation[](1); + PackedUserOperation[] memory userOps = new PackedUserOperation[](1); userOps[0] = userOp; entryPoint.handleOps(userOps, beneficiary); diff --git a/test/account/ValidationIntersection.t.sol b/test/account/ValidationIntersection.t.sol index 0ed7329c..fdfcfa7c 100644 --- a/test/account/ValidationIntersection.t.sol +++ b/test/account/ValidationIntersection.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.19; -import {UserOperation} from "@eth-infinitism/account-abstraction/interfaces/UserOperation.sol"; +import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interfaces/PackedUserOperation.sol"; import {UpgradeableModularAccount} from "../../src/account/UpgradeableModularAccount.sol"; import {FunctionReference} from "../../src/helpers/FunctionReferenceLib.sol"; @@ -51,7 +51,7 @@ contract ValidationIntersectionTest is AccountTestBase { function testFuzz_validationIntersect_single(uint256 validationData) public { noHookPlugin.setValidationData(validationData); - UserOperation memory userOp; + PackedUserOperation memory userOp; userOp.callData = bytes.concat(noHookPlugin.foo.selector); bytes32 uoHash = entryPoint.getUserOpHash(userOp); @@ -67,7 +67,7 @@ contract ValidationIntersectionTest is AccountTestBase { 0 // returns OK ); - UserOperation memory userOp; + PackedUserOperation memory userOp; userOp.callData = bytes.concat(oneHookPlugin.bar.selector); bytes32 uoHash = entryPoint.getUserOpHash(userOp); @@ -84,7 +84,7 @@ contract ValidationIntersectionTest is AccountTestBase { _SIG_VALIDATION_FAILED ); - UserOperation memory userOp; + PackedUserOperation memory userOp; userOp.callData = bytes.concat(oneHookPlugin.bar.selector); bytes32 uoHash = entryPoint.getUserOpHash(userOp); @@ -106,7 +106,7 @@ contract ValidationIntersectionTest is AccountTestBase { _packValidationData(address(0), start1, end1), _packValidationData(address(0), start2, end2) ); - UserOperation memory userOp; + PackedUserOperation memory userOp; userOp.callData = bytes.concat(oneHookPlugin.bar.selector); bytes32 uoHash = entryPoint.getUserOpHash(userOp); @@ -127,7 +127,7 @@ contract ValidationIntersectionTest is AccountTestBase { _packValidationData(address(0), start2, end2), _packValidationData(address(0), start1, end1) ); - UserOperation memory userOp; + PackedUserOperation memory userOp; userOp.callData = bytes.concat(oneHookPlugin.bar.selector); bytes32 uoHash = entryPoint.getUserOpHash(userOp); @@ -146,7 +146,7 @@ contract ValidationIntersectionTest is AccountTestBase { // do. ); - UserOperation memory userOp; + PackedUserOperation memory userOp; userOp.callData = bytes.concat(oneHookPlugin.bar.selector); bytes32 uoHash = entryPoint.getUserOpHash(userOp); @@ -170,7 +170,7 @@ contract ValidationIntersectionTest is AccountTestBase { 0 // returns OK ); - UserOperation memory userOp; + PackedUserOperation memory userOp; userOp.callData = bytes.concat(oneHookPlugin.bar.selector); bytes32 uoHash = entryPoint.getUserOpHash(userOp); @@ -193,7 +193,7 @@ contract ValidationIntersectionTest is AccountTestBase { _packValidationData(goodAuthorizer, start1, end1), _packValidationData(address(0), start2, end2) ); - UserOperation memory userOp; + PackedUserOperation memory userOp; userOp.callData = bytes.concat(oneHookPlugin.bar.selector); bytes32 uoHash = entryPoint.getUserOpHash(userOp); @@ -216,7 +216,7 @@ contract ValidationIntersectionTest is AccountTestBase { _packValidationData(address(0), start2, end2) ); - UserOperation memory userOp; + PackedUserOperation memory userOp; userOp.callData = bytes.concat(twoHookPlugin.baz.selector); bytes32 uoHash = entryPoint.getUserOpHash(userOp); @@ -233,7 +233,7 @@ contract ValidationIntersectionTest is AccountTestBase { _SIG_VALIDATION_FAILED ); - UserOperation memory userOp; + PackedUserOperation memory userOp; userOp.callData = bytes.concat(twoHookPlugin.baz.selector); bytes32 uoHash = entryPoint.getUserOpHash(userOp); diff --git a/test/comparison/CompareSimpleAccount.t.sol b/test/comparison/CompareSimpleAccount.t.sol index e9ea4cc2..88512560 100644 --- a/test/comparison/CompareSimpleAccount.t.sol +++ b/test/comparison/CompareSimpleAccount.t.sol @@ -5,7 +5,7 @@ import {Test} from "forge-std/Test.sol"; import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import {EntryPoint} from "@eth-infinitism/account-abstraction/core/EntryPoint.sol"; -import {UserOperation} from "@eth-infinitism/account-abstraction/interfaces/UserOperation.sol"; +import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interfaces/PackedUserOperation.sol"; import {SimpleAccount} from "@eth-infinitism/account-abstraction/samples/SimpleAccount.sol"; import {SimpleAccountFactory} from "@eth-infinitism/account-abstraction/samples/SimpleAccountFactory.sol"; @@ -54,7 +54,7 @@ contract CompareSimpleAccountTest is Test { } function test_SimpleAccount_deploy_basicSend() public { - UserOperation memory userOp = UserOperation({ + PackedUserOperation memory userOp = PackedUserOperation({ sender: account1, nonce: 0, initCode: abi.encodePacked(address(factory), abi.encodeCall(factory.createAccount, (owner1, 0))), @@ -72,14 +72,14 @@ contract CompareSimpleAccountTest is Test { (uint8 v, bytes32 r, bytes32 s) = vm.sign(owner1Key, userOpHash.toEthSignedMessageHash()); userOp.signature = abi.encodePacked(r, s, v); - UserOperation[] memory userOps = new UserOperation[](1); + PackedUserOperation[] memory userOps = new PackedUserOperation[](1); userOps[0] = userOp; entryPoint.handleOps(userOps, beneficiary); } function test_SimpleAccount_deploy_empty() public { - UserOperation memory userOp = UserOperation({ + PackedUserOperation memory userOp = PackedUserOperation({ sender: account1, nonce: 0, initCode: abi.encodePacked(address(factory), abi.encodeCall(factory.createAccount, (owner1, 0))), @@ -97,14 +97,14 @@ contract CompareSimpleAccountTest is Test { (uint8 v, bytes32 r, bytes32 s) = vm.sign(owner1Key, userOpHash.toEthSignedMessageHash()); userOp.signature = abi.encodePacked(r, s, v); - UserOperation[] memory userOps = new UserOperation[](1); + PackedUserOperation[] memory userOps = new PackedUserOperation[](1); userOps[0] = userOp; entryPoint.handleOps(userOps, beneficiary); } function test_SimpleAccount_postDeploy_basicSend() public { - UserOperation memory userOp = UserOperation({ + PackedUserOperation memory userOp = PackedUserOperation({ sender: account2, nonce: 0, initCode: "", @@ -122,20 +122,20 @@ contract CompareSimpleAccountTest is Test { (uint8 v, bytes32 r, bytes32 s) = vm.sign(owner2Key, userOpHash.toEthSignedMessageHash()); userOp.signature = abi.encodePacked(r, s, v); - UserOperation[] memory userOps = new UserOperation[](1); + PackedUserOperation[] memory userOps = new PackedUserOperation[](1); userOps[0] = userOp; entryPoint.handleOps(userOps, beneficiary); } function test_SimpleAccount_postDeploy_contractInteraction() public { - UserOperation memory userOp = UserOperation({ + PackedUserOperation memory userOp = PackedUserOperation({ sender: account2, nonce: 0, initCode: "", callData: abi.encodeCall( SimpleAccount.execute, (address(counter), 0, abi.encodeCall(Counter.increment, ())) - ), + ), callGasLimit: 5000000, verificationGasLimit: 5000000, preVerificationGas: 0, @@ -149,7 +149,7 @@ contract CompareSimpleAccountTest is Test { (uint8 v, bytes32 r, bytes32 s) = vm.sign(owner2Key, userOpHash.toEthSignedMessageHash()); userOp.signature = abi.encodePacked(r, s, v); - UserOperation[] memory userOps = new UserOperation[](1); + PackedUserOperation[] memory userOps = new PackedUserOperation[](1); userOps[0] = userOp; entryPoint.handleOps(userOps, beneficiary); diff --git a/test/mocks/MSCAFactoryFixture.sol b/test/mocks/MSCAFactoryFixture.sol index 17be2cc0..7cab98b1 100644 --- a/test/mocks/MSCAFactoryFixture.sol +++ b/test/mocks/MSCAFactoryFixture.sol @@ -44,7 +44,7 @@ contract MSCAFactoryFixture is OptimizedTest { /** * create an account, and return its address. * returns the address even if the account is already deployed. - * Note that during UserOperation execution, this method is called only if the account is not deployed. + * Note that during PackedUserOperation execution, this method is called only if the account is not deployed. * This method returns an existing account address so that entryPoint.getSenderAddress() would work even after * account creation */ diff --git a/test/mocks/plugins/ComprehensivePlugin.sol b/test/mocks/plugins/ComprehensivePlugin.sol index 442b39a6..0c7700f1 100644 --- a/test/mocks/plugins/ComprehensivePlugin.sol +++ b/test/mocks/plugins/ComprehensivePlugin.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.19; -import {UserOperation} from "@eth-infinitism/account-abstraction/interfaces/UserOperation.sol"; +import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interfaces/PackedUserOperation.sol"; import { ManifestExecutionHook, @@ -45,7 +45,7 @@ contract ComprehensivePlugin is BasePlugin { function onUninstall(bytes calldata) external override {} - function preUserOpValidationHook(uint8 functionId, UserOperation calldata, bytes32) + function preUserOpValidationHook(uint8 functionId, PackedUserOperation calldata, bytes32) external pure override @@ -59,7 +59,7 @@ contract ComprehensivePlugin is BasePlugin { revert NotImplemented(); } - function userOpValidationFunction(uint8 functionId, UserOperation calldata, bytes32) + function userOpValidationFunction(uint8 functionId, PackedUserOperation calldata, bytes32) external pure override diff --git a/test/mocks/plugins/ValidationPluginMocks.sol b/test/mocks/plugins/ValidationPluginMocks.sol index 4859a7e9..fb47a604 100644 --- a/test/mocks/plugins/ValidationPluginMocks.sol +++ b/test/mocks/plugins/ValidationPluginMocks.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.19; -import {UserOperation} from "@eth-infinitism/account-abstraction/interfaces/UserOperation.sol"; +import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interfaces/PackedUserOperation.sol"; import { ManifestFunction, @@ -30,7 +30,7 @@ abstract contract MockBaseUserOpValidationPlugin is BaseTestPlugin { function onUninstall(bytes calldata) external override {} - function preUserOpValidationHook(uint8 functionId, UserOperation calldata, bytes32) + function preUserOpValidationHook(uint8 functionId, PackedUserOperation calldata, bytes32) external view override @@ -44,7 +44,7 @@ abstract contract MockBaseUserOpValidationPlugin is BaseTestPlugin { revert NotImplemented(); } - function userOpValidationFunction(uint8 functionId, UserOperation calldata, bytes32) + function userOpValidationFunction(uint8 functionId, PackedUserOperation calldata, bytes32) external view override diff --git a/test/plugin/SingleOwnerPlugin.t.sol b/test/plugin/SingleOwnerPlugin.t.sol index 5784059e..73e45648 100644 --- a/test/plugin/SingleOwnerPlugin.t.sol +++ b/test/plugin/SingleOwnerPlugin.t.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.19; import {EntryPoint} from "@eth-infinitism/account-abstraction/core/EntryPoint.sol"; -import {UserOperation} from "@eth-infinitism/account-abstraction/interfaces/UserOperation.sol"; +import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interfaces/PackedUserOperation.sol"; import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import {SingleOwnerPlugin} from "../../src/plugins/owner/SingleOwnerPlugin.sol"; @@ -123,7 +123,7 @@ contract SingleOwnerPluginTest is OptimizedTest { ); } - function testFuzz_validateUserOpSig(string memory salt, UserOperation memory userOp) public { + function testFuzz_validateUserOpSig(string memory salt, PackedUserOperation memory userOp) public { // range bound the possible set of priv keys (address signer, uint256 privateKey) = makeAddrAndKey(salt); diff --git a/test/samples/plugins/ModularSessionKeyPlugin.t.sol b/test/samples/plugins/ModularSessionKeyPlugin.t.sol index 5001e56f..92ee87f6 100644 --- a/test/samples/plugins/ModularSessionKeyPlugin.t.sol +++ b/test/samples/plugins/ModularSessionKeyPlugin.t.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.19; // import {Test} from "forge-std/Test.sol"; // import {EntryPoint} from "@eth-infinitism/account-abstraction/core/EntryPoint.sol"; -// import {UserOperation} from "@eth-infinitism/account-abstraction/interfaces/UserOperation.sol"; +// import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interfaces/PackedUserOperation.sol"; // import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; // import {SingleOwnerPlugin} from "../../../src/plugins/owner/SingleOwnerPlugin.sol"; @@ -196,9 +196,9 @@ pragma solidity ^0.8.19; // } // function test_sessionKey_userOp() public { -// UserOperation[] memory userOps = new UserOperation[](1); +// PackedUserOperation[] memory userOps = new PackedUserOperation[](1); -// (, UserOperation memory userOp) = _constructUserOp(address(mockERC20), address(account), target, 1 +// (, PackedUserOperation memory userOp) = _constructUserOp(address(mockERC20), address(account), target, 1 // ether); // userOps[0] = userOp; @@ -252,10 +252,10 @@ pragma solidity ^0.8.19; // function test_sessionKey_invalidContractFails() public { // address wrongERC20Contract = makeAddr("wrongERC20Contract"); -// (bytes32 userOpHash, UserOperation memory userOp) = +// (bytes32 userOpHash, PackedUserOperation memory userOp) = // _constructUserOp(address(wrongERC20Contract), address(account), target, 1 ether); -// UserOperation[] memory userOps = new UserOperation[](1); +// PackedUserOperation[] memory userOps = new PackedUserOperation[](1); // userOps[0] = userOp; // bytes memory revertCallData = abi.encodeWithSelector( @@ -346,12 +346,12 @@ pragma solidity ^0.8.19; // function _constructUserOp(address targetContract, address from, address to, uint256 amount) // internal // view -// returns (bytes32, UserOperation memory) +// returns (bytes32, PackedUserOperation memory) // { // bytes memory userOpCallData = // abi.encodeCall(TokenSessionKeyPlugin.transferFromSessionKey, (targetContract, from, to, amount)); -// UserOperation memory userOp = UserOperation({ +// PackedUserOperation memory userOp = PackedUserOperation({ // sender: address(account), // nonce: 0, // initCode: "", From 5b2e647d822066cc52f29205032c9fd787797390 Mon Sep 17 00:00:00 2001 From: howydev <132113803+howydev@users.noreply.github.com> Date: Sat, 20 Apr 2024 17:04:47 -0400 Subject: [PATCH 3/6] chore: update PackedUO struct usage --- test/account/UpgradeableModularAccount.t.sol | 41 ++++++++------------ test/comparison/CompareSimpleAccount.t.sol | 32 +++++++-------- 2 files changed, 33 insertions(+), 40 deletions(-) diff --git a/test/account/UpgradeableModularAccount.t.sol b/test/account/UpgradeableModularAccount.t.sol index 6d4ebeeb..2fe236ac 100644 --- a/test/account/UpgradeableModularAccount.t.sol +++ b/test/account/UpgradeableModularAccount.t.sol @@ -42,6 +42,11 @@ contract UpgradeableModularAccountTest is AccountTestBase { event PluginUninstalled(address indexed plugin, bool indexed callbacksSucceeded); event ReceivedCall(bytes msgData, uint256 msgValue); + // helper function to compress 2 gas values into a single bytes32 + function _encodeGas(uint256 g1, uint256 g2) internal pure returns (bytes32) { + return bytes32(uint256(g1 << 128 + uint128(g2))); + } + function setUp() public { tokenReceiverPlugin = _deployTokenReceiverPlugin(); @@ -67,11 +72,9 @@ contract UpgradeableModularAccountTest is AccountTestBase { nonce: 0, initCode: "", callData: abi.encodeCall(UpgradeableModularAccount.execute, (ethRecipient, 1 wei, "")), - callGasLimit: CALL_GAS_LIMIT, - verificationGasLimit: VERIFICATION_GAS_LIMIT, + accountGasLimits: _encodeGas(VERIFICATION_GAS_LIMIT, CALL_GAS_LIMIT), preVerificationGas: 0, - maxFeePerGas: 1, - maxPriorityFeePerGas: 1, + gasFees: _encodeGas(1, 1), paymasterAndData: "", signature: "" }); @@ -95,11 +98,9 @@ contract UpgradeableModularAccountTest is AccountTestBase { nonce: 0, initCode: abi.encodePacked(address(factory), abi.encodeCall(factory.createAccount, (owner2, 0))), callData: abi.encodeCall(SingleOwnerPlugin.transferOwnership, (owner2)), - callGasLimit: CALL_GAS_LIMIT, - verificationGasLimit: VERIFICATION_GAS_LIMIT, + accountGasLimits: _encodeGas(VERIFICATION_GAS_LIMIT, CALL_GAS_LIMIT), preVerificationGas: 0, - maxFeePerGas: 2, - maxPriorityFeePerGas: 1, + gasFees: _encodeGas(1, 2), paymasterAndData: "", signature: "" }); @@ -123,11 +124,9 @@ contract UpgradeableModularAccountTest is AccountTestBase { nonce: 0, initCode: abi.encodePacked(address(factory), abi.encodeCall(factory.createAccount, (owner2, 0))), callData: abi.encodeCall(UpgradeableModularAccount.execute, (recipient, 1 wei, "")), - callGasLimit: CALL_GAS_LIMIT, - verificationGasLimit: VERIFICATION_GAS_LIMIT, + accountGasLimits: _encodeGas(VERIFICATION_GAS_LIMIT, CALL_GAS_LIMIT), preVerificationGas: 0, - maxFeePerGas: 2, - maxPriorityFeePerGas: 1, + gasFees: _encodeGas(1, 1), paymasterAndData: "", signature: "" }); @@ -151,11 +150,9 @@ contract UpgradeableModularAccountTest is AccountTestBase { nonce: 0, initCode: "", callData: abi.encodeCall(UpgradeableModularAccount.execute, (ethRecipient, 1 wei, "")), - callGasLimit: CALL_GAS_LIMIT, - verificationGasLimit: VERIFICATION_GAS_LIMIT, + accountGasLimits: _encodeGas(VERIFICATION_GAS_LIMIT, CALL_GAS_LIMIT), preVerificationGas: 0, - maxFeePerGas: 1, - maxPriorityFeePerGas: 1, + gasFees: _encodeGas(1, 1), paymasterAndData: "", signature: "" }); @@ -181,11 +178,9 @@ contract UpgradeableModularAccountTest is AccountTestBase { callData: abi.encodeCall( UpgradeableModularAccount.execute, (address(counter), 0, abi.encodeCall(counter.increment, ())) ), - callGasLimit: CALL_GAS_LIMIT, - verificationGasLimit: VERIFICATION_GAS_LIMIT, + accountGasLimits: _encodeGas(VERIFICATION_GAS_LIMIT, CALL_GAS_LIMIT), preVerificationGas: 0, - maxFeePerGas: 1, - maxPriorityFeePerGas: 1, + gasFees: _encodeGas(1, 1), paymasterAndData: "", signature: "" }); @@ -214,11 +209,9 @@ contract UpgradeableModularAccountTest is AccountTestBase { nonce: 0, initCode: "", callData: abi.encodeCall(UpgradeableModularAccount.executeBatch, (calls)), - callGasLimit: CALL_GAS_LIMIT, - verificationGasLimit: VERIFICATION_GAS_LIMIT, + accountGasLimits: _encodeGas(VERIFICATION_GAS_LIMIT, CALL_GAS_LIMIT), preVerificationGas: 0, - maxFeePerGas: 1, - maxPriorityFeePerGas: 1, + gasFees: _encodeGas(1, 1), paymasterAndData: "", signature: "" }); diff --git a/test/comparison/CompareSimpleAccount.t.sol b/test/comparison/CompareSimpleAccount.t.sol index 88512560..ff32a77d 100644 --- a/test/comparison/CompareSimpleAccount.t.sol +++ b/test/comparison/CompareSimpleAccount.t.sol @@ -32,6 +32,14 @@ contract CompareSimpleAccountTest is Test { Counter public counter; + uint256 public constant CALL_GAS_LIMIT = 500000; + uint256 public constant VERIFICATION_GAS_LIMIT = 500000; + + // helper function to compress 2 gas values into a single bytes32 + function _encodeGas(uint256 g1, uint256 g2) internal pure returns (bytes32) { + return bytes32(uint256(g1 << 128 + uint128(g2))); + } + function setUp() public { entryPoint = new EntryPoint(); (owner1, owner1Key) = makeAddrAndKey("owner1"); @@ -59,11 +67,9 @@ contract CompareSimpleAccountTest is Test { nonce: 0, initCode: abi.encodePacked(address(factory), abi.encodeCall(factory.createAccount, (owner1, 0))), callData: abi.encodeCall(SimpleAccount.execute, (beneficiary, 1, "")), - callGasLimit: 5000000, - verificationGasLimit: 5000000, + accountGasLimits: _encodeGas(VERIFICATION_GAS_LIMIT, CALL_GAS_LIMIT), preVerificationGas: 0, - maxFeePerGas: 2, - maxPriorityFeePerGas: 1, + gasFees: _encodeGas(1, 2), paymasterAndData: "", signature: "" }); @@ -84,11 +90,9 @@ contract CompareSimpleAccountTest is Test { nonce: 0, initCode: abi.encodePacked(address(factory), abi.encodeCall(factory.createAccount, (owner1, 0))), callData: "", - callGasLimit: 5000000, - verificationGasLimit: 5000000, + accountGasLimits: _encodeGas(VERIFICATION_GAS_LIMIT, CALL_GAS_LIMIT), preVerificationGas: 0, - maxFeePerGas: 2, - maxPriorityFeePerGas: 1, + gasFees: _encodeGas(1, 2), paymasterAndData: "", signature: "" }); @@ -109,11 +113,9 @@ contract CompareSimpleAccountTest is Test { nonce: 0, initCode: "", callData: abi.encodeCall(SimpleAccount.execute, (beneficiary, 1, "")), - callGasLimit: 5000000, - verificationGasLimit: 5000000, + accountGasLimits: _encodeGas(VERIFICATION_GAS_LIMIT, CALL_GAS_LIMIT), preVerificationGas: 0, - maxFeePerGas: 2, - maxPriorityFeePerGas: 1, + gasFees: _encodeGas(1, 2), paymasterAndData: "", signature: "" }); @@ -136,11 +138,9 @@ contract CompareSimpleAccountTest is Test { callData: abi.encodeCall( SimpleAccount.execute, (address(counter), 0, abi.encodeCall(Counter.increment, ())) ), - callGasLimit: 5000000, - verificationGasLimit: 5000000, + accountGasLimits: _encodeGas(VERIFICATION_GAS_LIMIT, CALL_GAS_LIMIT), preVerificationGas: 0, - maxFeePerGas: 2, - maxPriorityFeePerGas: 1, + gasFees: _encodeGas(1, 2), paymasterAndData: "", signature: "" }); From b979477961eff9d2c1e252d1ecb1041d1f645232 Mon Sep 17 00:00:00 2001 From: howy <132113803+howydev@users.noreply.github.com> Date: Mon, 22 Apr 2024 16:12:49 -0400 Subject: [PATCH 4/6] Update test/mocks/MSCAFactoryFixture.sol Co-authored-by: adam-alchemy <127769144+adam-alchemy@users.noreply.github.com> --- test/mocks/MSCAFactoryFixture.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/mocks/MSCAFactoryFixture.sol b/test/mocks/MSCAFactoryFixture.sol index 7cab98b1..cc8ae60a 100644 --- a/test/mocks/MSCAFactoryFixture.sol +++ b/test/mocks/MSCAFactoryFixture.sol @@ -44,7 +44,7 @@ contract MSCAFactoryFixture is OptimizedTest { /** * create an account, and return its address. * returns the address even if the account is already deployed. - * Note that during PackedUserOperation execution, this method is called only if the account is not deployed. + * Note that during user operation execution, this method is called only if the account is not deployed. * This method returns an existing account address so that entryPoint.getSenderAddress() would work even after * account creation */ From edf1b54cf58b6666a28508ed5a592d4962ab1f03 Mon Sep 17 00:00:00 2001 From: howydev <132113803+howydev@users.noreply.github.com> Date: Tue, 23 Apr 2024 13:50:47 -0400 Subject: [PATCH 5/6] fix: move helper function to test base, lint --- lib/openzeppelin-contracts | 2 +- test/account/UpgradeableModularAccount.t.sol | 7 +------ test/comparison/CompareSimpleAccount.t.sol | 2 +- test/utils/AccountTestBase.sol | 5 +++++ 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/openzeppelin-contracts b/lib/openzeppelin-contracts index e1b3d8c7..932fddf6 160000 --- a/lib/openzeppelin-contracts +++ b/lib/openzeppelin-contracts @@ -1 +1 @@ -Subproject commit e1b3d8c7ee2c97868f4ab107fe8b7e19f0a8db9f +Subproject commit 932fddf69a699a9a80fd2396fd1a2ab91cdda123 diff --git a/test/account/UpgradeableModularAccount.t.sol b/test/account/UpgradeableModularAccount.t.sol index 2fe236ac..ae491c13 100644 --- a/test/account/UpgradeableModularAccount.t.sol +++ b/test/account/UpgradeableModularAccount.t.sol @@ -42,11 +42,6 @@ contract UpgradeableModularAccountTest is AccountTestBase { event PluginUninstalled(address indexed plugin, bool indexed callbacksSucceeded); event ReceivedCall(bytes msgData, uint256 msgValue); - // helper function to compress 2 gas values into a single bytes32 - function _encodeGas(uint256 g1, uint256 g2) internal pure returns (bytes32) { - return bytes32(uint256(g1 << 128 + uint128(g2))); - } - function setUp() public { tokenReceiverPlugin = _deployTokenReceiverPlugin(); @@ -177,7 +172,7 @@ contract UpgradeableModularAccountTest is AccountTestBase { initCode: "", callData: abi.encodeCall( UpgradeableModularAccount.execute, (address(counter), 0, abi.encodeCall(counter.increment, ())) - ), + ), accountGasLimits: _encodeGas(VERIFICATION_GAS_LIMIT, CALL_GAS_LIMIT), preVerificationGas: 0, gasFees: _encodeGas(1, 1), diff --git a/test/comparison/CompareSimpleAccount.t.sol b/test/comparison/CompareSimpleAccount.t.sol index ff32a77d..7c3182b2 100644 --- a/test/comparison/CompareSimpleAccount.t.sol +++ b/test/comparison/CompareSimpleAccount.t.sol @@ -137,7 +137,7 @@ contract CompareSimpleAccountTest is Test { initCode: "", callData: abi.encodeCall( SimpleAccount.execute, (address(counter), 0, abi.encodeCall(Counter.increment, ())) - ), + ), accountGasLimits: _encodeGas(VERIFICATION_GAS_LIMIT, CALL_GAS_LIMIT), preVerificationGas: 0, gasFees: _encodeGas(1, 2), diff --git a/test/utils/AccountTestBase.sol b/test/utils/AccountTestBase.sol index 9738d3ab..e23ed1ee 100644 --- a/test/utils/AccountTestBase.sol +++ b/test/utils/AccountTestBase.sol @@ -39,4 +39,9 @@ abstract contract AccountTestBase is OptimizedTest { vm.prank(owner1); SingleOwnerPlugin(address(account1)).transferOwnership(address(this)); } + + // helper function to compress 2 gas values into a single bytes32 + function _encodeGas(uint256 g1, uint256 g2) internal pure returns (bytes32) { + return bytes32(uint256(g1 << 128 + uint128(g2))); + } } From 145acbb7b19f58a1aa9ffc1a10b5fed82ab70295 Mon Sep 17 00:00:00 2001 From: howy <132113803+howydev@users.noreply.github.com> Date: Wed, 1 May 2024 14:39:33 -0400 Subject: [PATCH 6/6] chore: update to 4337 v0.7 (2/n) (#49) --- src/account/AccountLoupe.sol | 1 - src/account/AccountStorageInitializable.sol | 72 +++++++++++------ src/account/UpgradeableModularAccount.sol | 7 +- src/plugins/TokenReceiverPlugin.sol | 34 +++----- src/plugins/owner/SingleOwnerPlugin.sol | 12 ++- test/account/UpgradeableModularAccount.t.sol | 16 ++++ test/comparison/CompareSimpleAccount.t.sol | 4 +- test/libraries/AccountStorage.t.sol | 2 +- test/mocks/MockERC721.sol | 12 +++ test/mocks/MockERC777.sol | 51 ------------ test/plugin/SingleOwnerPlugin.t.sol | 2 + test/plugin/TokenReceiverPlugin.t.sol | 82 ++++++++------------ test/utils/AccountTestBase.sol | 2 +- 13 files changed, 129 insertions(+), 168 deletions(-) create mode 100644 test/mocks/MockERC721.sol delete mode 100644 test/mocks/MockERC777.sol diff --git a/src/account/AccountLoupe.sol b/src/account/AccountLoupe.sol index 8bff326c..a75def37 100644 --- a/src/account/AccountLoupe.sol +++ b/src/account/AccountLoupe.sol @@ -24,7 +24,6 @@ abstract contract AccountLoupe is IAccountLoupe { if ( selector == IStandardExecutor.execute.selector || selector == IStandardExecutor.executeBatch.selector - || selector == UUPSUpgradeable.upgradeTo.selector || selector == UUPSUpgradeable.upgradeToAndCall.selector || selector == IPluginManager.installPlugin.selector || selector == IPluginManager.uninstallPlugin.selector diff --git a/src/account/AccountStorageInitializable.sol b/src/account/AccountStorageInitializable.sol index 5131978b..debcee40 100644 --- a/src/account/AccountStorageInitializable.sol +++ b/src/account/AccountStorageInitializable.sol @@ -1,45 +1,67 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.25; -import {Address} from "@openzeppelin/contracts/utils/Address.sol"; - import {AccountStorage, getAccountStorage} from "./AccountStorage.sol"; +/// @title AccountStorageInitializable +/// @dev Bulk of the impl is lifted from OZ 5.0 Initializible abstract contract AccountStorageInitializable { - error AlreadyInitialized(); - error AlreadyInitializing(); + /** + * @dev Triggered when the contract has been initialized or reinitialized. + */ + event Initialized(uint64 version); + + /** + * @dev The contract is already initialized. + */ + error InvalidInitialization(); + + /** + * @dev The contract is not initializing. + */ + error NotInitializing(); /// @notice Modifier to put on function intended to be called only once per implementation /// @dev Reverts if the contract has already been initialized modifier initializer() { - AccountStorage storage _storage = getAccountStorage(); - bool isTopLevelCall = !_storage.initializing; - if ( - isTopLevelCall && _storage.initialized < 1 - || !Address.isContract(address(this)) && _storage.initialized == 1 - ) { - _storage.initialized = 1; - if (isTopLevelCall) { - _storage.initializing = true; - } - _; - if (isTopLevelCall) { - _storage.initializing = false; - } - } else { - revert AlreadyInitialized(); + AccountStorage storage $ = getAccountStorage(); + + // Cache values to avoid duplicated sloads + bool isTopLevelCall = !$.initializing; + uint64 initialized = $.initialized; + + // Allowed calls: + // - initialSetup: the contract is not in the initializing state and no previous version was + // initialized + // - construction: the contract is initialized at version 1 (no reininitialization) and the + // current contract is just being deployed + bool initialSetup = initialized == 0 && isTopLevelCall; + bool construction = initialized == 1 && address(this).code.length == 0; + + if (!initialSetup && !construction) { + revert InvalidInitialization(); + } + $.initialized = 1; + if (isTopLevelCall) { + $.initializing = true; + } + _; + if (isTopLevelCall) { + $.initializing = false; + emit Initialized(1); } } /// @notice Internal function to disable calls to initialization functions /// @dev Reverts if the contract has already been initialized function _disableInitializers() internal virtual { - AccountStorage storage _storage = getAccountStorage(); - if (_storage.initializing) { - revert AlreadyInitializing(); + AccountStorage storage $ = getAccountStorage(); + if ($.initializing) { + revert InvalidInitialization(); } - if (_storage.initialized != type(uint8).max) { - _storage.initialized = type(uint8).max; + if ($.initialized != type(uint8).max) { + $.initialized = type(uint8).max; + emit Initialized(type(uint8).max); } } } diff --git a/src/account/UpgradeableModularAccount.sol b/src/account/UpgradeableModularAccount.sol index 81496a2a..f29d17c7 100644 --- a/src/account/UpgradeableModularAccount.sol +++ b/src/account/UpgradeableModularAccount.sol @@ -292,11 +292,6 @@ contract UpgradeableModularAccount is return getAccountStorage().supportedIfaces[interfaceId] > 0; } - /// @inheritdoc UUPSUpgradeable - function upgradeTo(address newImplementation) public override onlyProxy wrapNativeFunction { - _upgradeToAndCallUUPS(newImplementation, new bytes(0), false); - } - /// @inheritdoc UUPSUpgradeable function upgradeToAndCall(address newImplementation, bytes memory data) public @@ -305,7 +300,7 @@ contract UpgradeableModularAccount is onlyProxy wrapNativeFunction { - _upgradeToAndCallUUPS(newImplementation, data, true); + super.upgradeToAndCall(newImplementation, data); } /// @notice Gets the entry point for this account diff --git a/src/plugins/TokenReceiverPlugin.sol b/src/plugins/TokenReceiverPlugin.sol index f22ae3ba..980d7397 100644 --- a/src/plugins/TokenReceiverPlugin.sol +++ b/src/plugins/TokenReceiverPlugin.sol @@ -2,7 +2,6 @@ pragma solidity ^0.8.25; import {IERC721Receiver} from "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol"; -import {IERC777Recipient} from "@openzeppelin/contracts/interfaces/IERC777Recipient.sol"; import {IERC1155Receiver} from "@openzeppelin/contracts/interfaces/IERC1155Receiver.sol"; import { @@ -18,7 +17,7 @@ import {BasePlugin} from "./BasePlugin.sol"; /// @author ERC-6900 Authors /// @notice This plugin allows modular accounts to receive various types of tokens by implementing /// required token receiver interfaces. -contract TokenReceiverPlugin is BasePlugin, IERC721Receiver, IERC777Recipient, IERC1155Receiver { +contract TokenReceiverPlugin is BasePlugin, IERC721Receiver, IERC1155Receiver { string public constant NAME = "Token Receiver Plugin"; string public constant VERSION = "1.0.0"; string public constant AUTHOR = "ERC-6900 Authors"; @@ -27,13 +26,6 @@ contract TokenReceiverPlugin is BasePlugin, IERC721Receiver, IERC777Recipient, I // ┃ Execution functions ┃ // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ - function tokensReceived(address, address, address, uint256, bytes calldata, bytes calldata) - external - pure - override - // solhint-disable-next-line no-empty-blocks - {} - function onERC721Received(address, address, uint256, bytes calldata) external pure override returns (bytes4) { return IERC721Receiver.onERC721Received.selector; } @@ -72,11 +64,10 @@ contract TokenReceiverPlugin is BasePlugin, IERC721Receiver, IERC777Recipient, I function pluginManifest() external pure override returns (PluginManifest memory) { PluginManifest memory manifest; - manifest.executionFunctions = new bytes4[](4); - manifest.executionFunctions[0] = this.tokensReceived.selector; - manifest.executionFunctions[1] = this.onERC721Received.selector; - manifest.executionFunctions[2] = this.onERC1155Received.selector; - manifest.executionFunctions[3] = this.onERC1155BatchReceived.selector; + manifest.executionFunctions = new bytes4[](3); + manifest.executionFunctions[0] = this.onERC721Received.selector; + manifest.executionFunctions[1] = this.onERC1155Received.selector; + manifest.executionFunctions[2] = this.onERC1155BatchReceived.selector; // Only runtime validationFunction is needed since callbacks come from token contracts only ManifestFunction memory alwaysAllowRuntime = ManifestFunction({ @@ -84,28 +75,23 @@ contract TokenReceiverPlugin is BasePlugin, IERC721Receiver, IERC777Recipient, I functionId: 0, // Unused. dependencyIndex: 0 // Unused. }); - manifest.validationFunctions = new ManifestAssociatedFunction[](4); + manifest.validationFunctions = new ManifestAssociatedFunction[](3); manifest.validationFunctions[0] = ManifestAssociatedFunction({ - executionSelector: this.tokensReceived.selector, - associatedFunction: alwaysAllowRuntime - }); - manifest.validationFunctions[1] = ManifestAssociatedFunction({ executionSelector: this.onERC721Received.selector, associatedFunction: alwaysAllowRuntime }); - manifest.validationFunctions[2] = ManifestAssociatedFunction({ + manifest.validationFunctions[1] = ManifestAssociatedFunction({ executionSelector: this.onERC1155Received.selector, associatedFunction: alwaysAllowRuntime }); - manifest.validationFunctions[3] = ManifestAssociatedFunction({ + manifest.validationFunctions[2] = ManifestAssociatedFunction({ executionSelector: this.onERC1155BatchReceived.selector, associatedFunction: alwaysAllowRuntime }); - manifest.interfaceIds = new bytes4[](3); + manifest.interfaceIds = new bytes4[](2); manifest.interfaceIds[0] = type(IERC721Receiver).interfaceId; - manifest.interfaceIds[1] = type(IERC777Recipient).interfaceId; - manifest.interfaceIds[2] = type(IERC1155Receiver).interfaceId; + manifest.interfaceIds[1] = type(IERC1155Receiver).interfaceId; return manifest; } diff --git a/src/plugins/owner/SingleOwnerPlugin.sol b/src/plugins/owner/SingleOwnerPlugin.sol index bfff2aa4..b1d5d5e1 100644 --- a/src/plugins/owner/SingleOwnerPlugin.sol +++ b/src/plugins/owner/SingleOwnerPlugin.sol @@ -5,6 +5,7 @@ import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import {IERC1271} from "@openzeppelin/contracts/interfaces/IERC1271.sol"; import {SignatureChecker} from "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol"; import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interfaces/PackedUserOperation.sol"; +import {MessageHashUtils} from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol"; import {UUPSUpgradeable} from "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol"; import {IPluginManager} from "../../interfaces/IPluginManager.sol"; @@ -38,6 +39,7 @@ import {ISingleOwnerPlugin} from "./ISingleOwnerPlugin.sol"; /// send user operations through a bundler. contract SingleOwnerPlugin is BasePlugin, ISingleOwnerPlugin, IERC1271 { using ECDSA for bytes32; + using MessageHashUtils for bytes32; string public constant NAME = "Single Owner Plugin"; string public constant VERSION = "1.0.0"; @@ -99,7 +101,7 @@ contract SingleOwnerPlugin is BasePlugin, ISingleOwnerPlugin, IERC1271 { { if (functionId == uint8(FunctionId.VALIDATION_OWNER_OR_SELF)) { // Validate the user op signature against the owner. - (address signer,) = (userOpHash.toEthSignedMessageHash()).tryRecover(userOp.signature); + (address signer,,) = (userOpHash.toEthSignedMessageHash()).tryRecover(userOp.signature); if (signer == address(0) || signer != _owners[msg.sender]) { return _SIG_VALIDATION_FAILED; } @@ -154,7 +156,7 @@ contract SingleOwnerPlugin is BasePlugin, ISingleOwnerPlugin, IERC1271 { functionId: uint8(FunctionId.VALIDATION_OWNER_OR_SELF), dependencyIndex: 0 // Unused. }); - manifest.validationFunctions = new ManifestAssociatedFunction[](8); + manifest.validationFunctions = new ManifestAssociatedFunction[](7); manifest.validationFunctions[0] = ManifestAssociatedFunction({ executionSelector: this.transferOwnership.selector, associatedFunction: ownerValidationFunction @@ -176,10 +178,6 @@ contract SingleOwnerPlugin is BasePlugin, ISingleOwnerPlugin, IERC1271 { associatedFunction: ownerValidationFunction }); manifest.validationFunctions[5] = ManifestAssociatedFunction({ - executionSelector: UUPSUpgradeable.upgradeTo.selector, - associatedFunction: ownerValidationFunction - }); - manifest.validationFunctions[6] = ManifestAssociatedFunction({ executionSelector: UUPSUpgradeable.upgradeToAndCall.selector, associatedFunction: ownerValidationFunction }); @@ -189,7 +187,7 @@ contract SingleOwnerPlugin is BasePlugin, ISingleOwnerPlugin, IERC1271 { functionId: 0, // Unused. dependencyIndex: 0 // Unused. }); - manifest.validationFunctions[7] = ManifestAssociatedFunction({ + manifest.validationFunctions[6] = ManifestAssociatedFunction({ executionSelector: this.isValidSignature.selector, associatedFunction: alwaysAllowRuntime }); diff --git a/test/account/UpgradeableModularAccount.t.sol b/test/account/UpgradeableModularAccount.t.sol index ae491c13..3ef6f107 100644 --- a/test/account/UpgradeableModularAccount.t.sol +++ b/test/account/UpgradeableModularAccount.t.sol @@ -5,6 +5,7 @@ import {console} from "forge-std/Test.sol"; import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interfaces/PackedUserOperation.sol"; +import {MessageHashUtils} from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol"; import {PluginManagerInternals} from "../../src/account/PluginManagerInternals.sol"; import {UpgradeableModularAccount} from "../../src/account/UpgradeableModularAccount.sol"; @@ -23,6 +24,7 @@ import {AccountTestBase} from "../utils/AccountTestBase.sol"; contract UpgradeableModularAccountTest is AccountTestBase { using ECDSA for bytes32; + using MessageHashUtils for bytes32; TokenReceiverPlugin public tokenReceiverPlugin; @@ -403,6 +405,20 @@ contract UpgradeableModularAccountTest is AccountTestBase { vm.stopPrank(); } + function test_upgradeToAndCall() public { + vm.startPrank(owner1); + UpgradeableModularAccount account3 = new UpgradeableModularAccount(entryPoint); + bytes32 slot = account3.proxiableUUID(); + + // account has impl from factory + assertEq( + address(factory.accountImplementation()), address(uint160(uint256(vm.load(address(account1), slot)))) + ); + account1.upgradeToAndCall(address(account3), bytes("")); + // account has new impl + assertEq(address(account3), address(uint160(uint256(vm.load(address(account1), slot))))); + } + // Internal Functions function _printStorageReadsAndWrites(address addr) internal { diff --git a/test/comparison/CompareSimpleAccount.t.sol b/test/comparison/CompareSimpleAccount.t.sol index 7c3182b2..93b75ebe 100644 --- a/test/comparison/CompareSimpleAccount.t.sol +++ b/test/comparison/CompareSimpleAccount.t.sol @@ -4,6 +4,7 @@ pragma solidity ^0.8.19; import {Test} from "forge-std/Test.sol"; import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; +import {MessageHashUtils} from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol"; import {EntryPoint} from "@eth-infinitism/account-abstraction/core/EntryPoint.sol"; import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interfaces/PackedUserOperation.sol"; @@ -14,6 +15,7 @@ import {Counter} from "../mocks/Counter.sol"; contract CompareSimpleAccountTest is Test { using ECDSA for bytes32; + using MessageHashUtils for bytes32; EntryPoint public entryPoint; address payable public beneficiary; @@ -37,7 +39,7 @@ contract CompareSimpleAccountTest is Test { // helper function to compress 2 gas values into a single bytes32 function _encodeGas(uint256 g1, uint256 g2) internal pure returns (bytes32) { - return bytes32(uint256(g1 << 128 + uint128(g2))); + return bytes32(uint256((g1 << 128) + uint128(g2))); } function setUp() public { diff --git a/test/libraries/AccountStorage.t.sol b/test/libraries/AccountStorage.t.sol index 7cab9991..f59049a3 100644 --- a/test/libraries/AccountStorage.t.sol +++ b/test/libraries/AccountStorage.t.sol @@ -22,7 +22,7 @@ contract AccountStorageTest is Test { assertEq(uint256(vm.load(address(impl), _ACCOUNT_STORAGE_SLOT)), type(uint8).max); // should revert if we try to initialize again - vm.expectRevert(AccountStorageInitializable.AlreadyInitialized.selector); + vm.expectRevert(AccountStorageInitializable.InvalidInitialization.selector); impl.initialize(); } diff --git a/test/mocks/MockERC721.sol b/test/mocks/MockERC721.sol new file mode 100644 index 00000000..1139adf2 --- /dev/null +++ b/test/mocks/MockERC721.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.19; + +import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; + +contract MockERC721 is ERC721 { + constructor(string memory name, string memory symbol) ERC721(name, symbol) {} + + function mint(address account, uint256 tokenId) external { + _mint(account, tokenId); + } +} diff --git a/test/mocks/MockERC777.sol b/test/mocks/MockERC777.sol deleted file mode 100644 index 18840db2..00000000 --- a/test/mocks/MockERC777.sol +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.19; - -import {IERC777} from "@openzeppelin/contracts/token/ERC777/IERC777.sol"; -import {IERC777Recipient} from "@openzeppelin/contracts/token/ERC777/IERC777Recipient.sol"; - -contract MockERC777 is IERC777 { - string public override name; - string public override symbol; - uint256 public override granularity; - uint256 public override totalSupply; - mapping(address => uint256) public override balanceOf; - - function mint(address to, uint256 amount) public { - balanceOf[to] += amount; - } - - function transfer(address to, uint256 amount) public returns (bool) { - return transferFrom(msg.sender, to, amount); - } - - function transferFrom(address from, address to, uint256 amount) public returns (bool) { - IERC777Recipient(to).tokensReceived(msg.sender, from, to, amount, bytes(""), bytes("")); - balanceOf[from] -= amount; - balanceOf[to] += amount; - return true; - } - - function send(address to, uint256 amount, bytes calldata) public override { - transferFrom(msg.sender, to, amount); - } - - function burn(uint256 amount, bytes calldata) external { - transferFrom(msg.sender, address(0), amount); - } - - function isOperatorFor(address, address) external pure returns (bool) { - return false; - } - - // solhint-disable-next-line no-empty-blocks - function authorizeOperator(address) external {} - // solhint-disable-next-line no-empty-blocks - function revokeOperator(address) external {} - // solhint-disable-next-line no-empty-blocks - function defaultOperators() external view returns (address[] memory a) {} - // solhint-disable-next-line no-empty-blocks - function operatorSend(address, address, uint256, bytes calldata, bytes calldata) external {} - // solhint-disable-next-line no-empty-blocks - function operatorBurn(address, uint256, bytes calldata, bytes calldata) external {} -} diff --git a/test/plugin/SingleOwnerPlugin.t.sol b/test/plugin/SingleOwnerPlugin.t.sol index 73e45648..dea5b2f9 100644 --- a/test/plugin/SingleOwnerPlugin.t.sol +++ b/test/plugin/SingleOwnerPlugin.t.sol @@ -4,6 +4,7 @@ pragma solidity ^0.8.19; import {EntryPoint} from "@eth-infinitism/account-abstraction/core/EntryPoint.sol"; import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interfaces/PackedUserOperation.sol"; import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; +import {MessageHashUtils} from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol"; import {SingleOwnerPlugin} from "../../src/plugins/owner/SingleOwnerPlugin.sol"; import {ISingleOwnerPlugin} from "../../src/plugins/owner/ISingleOwnerPlugin.sol"; @@ -12,6 +13,7 @@ import {OptimizedTest} from "../utils/OptimizedTest.sol"; contract SingleOwnerPluginTest is OptimizedTest { using ECDSA for bytes32; + using MessageHashUtils for bytes32; SingleOwnerPlugin public plugin; EntryPoint public entryPoint; diff --git a/test/plugin/TokenReceiverPlugin.t.sol b/test/plugin/TokenReceiverPlugin.t.sol index 49692e34..7a7433af 100644 --- a/test/plugin/TokenReceiverPlugin.t.sol +++ b/test/plugin/TokenReceiverPlugin.t.sol @@ -3,9 +3,6 @@ pragma solidity ^0.8.19; import {IEntryPoint} from "@eth-infinitism/account-abstraction/interfaces/IEntryPoint.sol"; import {IERC721Receiver} from "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol"; -import {ERC721PresetMinterPauserAutoId} from - "@openzeppelin/contracts/token/ERC721/presets/ERC721PresetMinterPauserAutoId.sol"; -import {IERC777Recipient} from "@openzeppelin/contracts/token/ERC777/IERC777Recipient.sol"; import {IERC1155Receiver} from "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol"; import {UpgradeableModularAccount} from "../../src/account/UpgradeableModularAccount.sol"; @@ -13,7 +10,7 @@ import {FunctionReference} from "../../src/helpers/FunctionReferenceLib.sol"; import {TokenReceiverPlugin} from "../../src/plugins/TokenReceiverPlugin.sol"; import {MSCAFactoryFixture} from "../mocks/MSCAFactoryFixture.sol"; -import {MockERC777} from "../mocks/MockERC777.sol"; +import {MockERC721} from "../mocks/MockERC721.sol"; import {MockERC1155} from "../mocks/MockERC1155.sol"; import {OptimizedTest} from "../utils/OptimizedTest.sol"; @@ -21,9 +18,8 @@ contract TokenReceiverPluginTest is OptimizedTest, IERC1155Receiver { UpgradeableModularAccount public acct; TokenReceiverPlugin public plugin; - ERC721PresetMinterPauserAutoId public t0; - MockERC777 public t1; - MockERC1155 public t2; + MockERC721 public t0; + MockERC1155 public t1; // init dynamic length arrays for use in args address[] public defaultOperators; @@ -41,16 +37,13 @@ contract TokenReceiverPluginTest is OptimizedTest, IERC1155Receiver { acct = factory.createAccount(address(this), 0); plugin = _deployTokenReceiverPlugin(); - t0 = new ERC721PresetMinterPauserAutoId("t0", "t0", ""); - t0.mint(address(this)); + t0 = new MockERC721("t0", "t0"); + t0.mint(address(this), _TOKEN_ID); - t1 = new MockERC777(); - t1.mint(address(this), _TOKEN_AMOUNT); - - t2 = new MockERC1155(); - t2.mint(address(this), _TOKEN_ID, _TOKEN_AMOUNT); + t1 = new MockERC1155(); + t1.mint(address(this), _TOKEN_ID, _TOKEN_AMOUNT); for (uint256 i = 1; i < _BATCH_TOKEN_IDS; i++) { - t2.mint(address(this), i, _TOKEN_AMOUNT); + t1.mint(address(this), i, _TOKEN_AMOUNT); tokenIds.push(i); tokenAmts.push(_TOKEN_AMOUNT); zeroTokenAmts.push(0); @@ -81,54 +74,45 @@ contract TokenReceiverPluginTest is OptimizedTest, IERC1155Receiver { assertEq(t0.ownerOf(_TOKEN_ID), address(acct)); } - function test_failERC777Transfer() public { + function test_failERC1155Transfer() public { + // for 1155, reverts are caught in a try catch and bubbled up with the reason from the account vm.expectRevert( abi.encodePacked( UpgradeableModularAccount.UnrecognizedFunction.selector, - IERC777Recipient.tokensReceived.selector, + IERC1155Receiver.onERC1155Received.selector, bytes28(0) ) ); - t1.transfer(address(acct), _TOKEN_AMOUNT); - } - - function test_passERC777Transfer() public { - _initPlugin(); - - assertEq(t1.balanceOf(address(this)), _TOKEN_AMOUNT); - assertEq(t1.balanceOf(address(acct)), 0); - t1.transfer(address(acct), _TOKEN_AMOUNT); - assertEq(t1.balanceOf(address(this)), 0); - assertEq(t1.balanceOf(address(acct)), _TOKEN_AMOUNT); - } - - function test_failERC1155Transfer() public { - // for 1155, reverts are caught in a try catch and bubbled up with a diff reason - vm.expectRevert("ERC1155: transfer to non-ERC1155Receiver implementer"); - t2.safeTransferFrom(address(this), address(acct), _TOKEN_ID, _TOKEN_AMOUNT, ""); + t1.safeTransferFrom(address(this), address(acct), _TOKEN_ID, _TOKEN_AMOUNT, ""); - // for 1155, reverts are caught in a try catch and bubbled up with a diff reason - vm.expectRevert("ERC1155: transfer to non-ERC1155Receiver implementer"); - t2.safeBatchTransferFrom(address(this), address(acct), tokenIds, tokenAmts, ""); + // for 1155, reverts are caught in a try catch and bubbled up with the reason from the account + vm.expectRevert( + abi.encodePacked( + UpgradeableModularAccount.UnrecognizedFunction.selector, + IERC1155Receiver.onERC1155BatchReceived.selector, + bytes28(0) + ) + ); + t1.safeBatchTransferFrom(address(this), address(acct), tokenIds, tokenAmts, ""); } function test_passERC1155Transfer() public { _initPlugin(); - assertEq(t2.balanceOf(address(this), _TOKEN_ID), _TOKEN_AMOUNT); - assertEq(t2.balanceOf(address(acct), _TOKEN_ID), 0); - t2.safeTransferFrom(address(this), address(acct), _TOKEN_ID, _TOKEN_AMOUNT, ""); - assertEq(t2.balanceOf(address(this), _TOKEN_ID), 0); - assertEq(t2.balanceOf(address(acct), _TOKEN_ID), _TOKEN_AMOUNT); + assertEq(t1.balanceOf(address(this), _TOKEN_ID), _TOKEN_AMOUNT); + assertEq(t1.balanceOf(address(acct), _TOKEN_ID), 0); + t1.safeTransferFrom(address(this), address(acct), _TOKEN_ID, _TOKEN_AMOUNT, ""); + assertEq(t1.balanceOf(address(this), _TOKEN_ID), 0); + assertEq(t1.balanceOf(address(acct), _TOKEN_ID), _TOKEN_AMOUNT); for (uint256 i = 1; i < _BATCH_TOKEN_IDS; i++) { - assertEq(t2.balanceOf(address(this), i), _TOKEN_AMOUNT); - assertEq(t2.balanceOf(address(acct), i), 0); + assertEq(t1.balanceOf(address(this), i), _TOKEN_AMOUNT); + assertEq(t1.balanceOf(address(acct), i), 0); } - t2.safeBatchTransferFrom(address(this), address(acct), tokenIds, tokenAmts, ""); + t1.safeBatchTransferFrom(address(this), address(acct), tokenIds, tokenAmts, ""); for (uint256 i = 1; i < _BATCH_TOKEN_IDS; i++) { - assertEq(t2.balanceOf(address(this), i), 0); - assertEq(t2.balanceOf(address(acct), i), _TOKEN_AMOUNT); + assertEq(t1.balanceOf(address(this), i), 0); + assertEq(t1.balanceOf(address(acct), i), _TOKEN_AMOUNT); } } @@ -137,8 +121,6 @@ contract TokenReceiverPluginTest is OptimizedTest, IERC1155Receiver { isSupported = acct.supportsInterface(type(IERC721Receiver).interfaceId); assertEq(isSupported, false); - isSupported = acct.supportsInterface(type(IERC777Recipient).interfaceId); - assertEq(isSupported, false); isSupported = acct.supportsInterface(type(IERC1155Receiver).interfaceId); assertEq(isSupported, false); } @@ -150,8 +132,6 @@ contract TokenReceiverPluginTest is OptimizedTest, IERC1155Receiver { isSupported = acct.supportsInterface(type(IERC721Receiver).interfaceId); assertEq(isSupported, true); - isSupported = acct.supportsInterface(type(IERC777Recipient).interfaceId); - assertEq(isSupported, true); isSupported = acct.supportsInterface(type(IERC1155Receiver).interfaceId); assertEq(isSupported, true); } diff --git a/test/utils/AccountTestBase.sol b/test/utils/AccountTestBase.sol index e23ed1ee..5d9880f9 100644 --- a/test/utils/AccountTestBase.sol +++ b/test/utils/AccountTestBase.sol @@ -42,6 +42,6 @@ abstract contract AccountTestBase is OptimizedTest { // helper function to compress 2 gas values into a single bytes32 function _encodeGas(uint256 g1, uint256 g2) internal pure returns (bytes32) { - return bytes32(uint256(g1 << 128 + uint128(g2))); + return bytes32(uint256((g1 << 128) + uint128(g2))); } }