Skip to content

Commit 11b7d48

Browse files
Amxxernestognw
andauthored
Update Account and Paymaster to use Entrypoint v0.8.0 (#95)
Co-authored-by: ernestognw <[email protected]>
1 parent cc554fc commit 11b7d48

22 files changed

+177
-261
lines changed

contracts/account/Account.sol

Lines changed: 1 addition & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -13,43 +13,10 @@ import {AccountCore} from "./AccountCore.sol";
1313
*
1414
* * {ERC721Holder} and {ERC1155Holder} to accept ERC-712 and ERC-1155 token transfers transfers.
1515
* * {ERC7739} for ERC-1271 signature support with ERC-7739 replay protection
16-
* * {ERC7821} for performing external calls in batches.
1716
*
1817
* TIP: Use {ERC7821} to enable external calls in batches.
1918
*
2019
* NOTE: To use this contract, the {ERC7739-_rawSignatureValidation} function must be
2120
* implemented using a specific signature verification algorithm. See {SignerECDSA}, {SignerP256} or {SignerRSA}.
2221
*/
23-
abstract contract Account is AccountCore, ERC721Holder, ERC1155Holder, ERC7739 {
24-
bytes32 private constant PACKED_USER_OPERATION =
25-
keccak256(
26-
"PackedUserOperation(address sender,uint256 nonce,bytes initCode,bytes callData,bytes32 accountGasLimits,uint256 preVerificationGas,bytes32 gasFees,bytes paymasterAndData)"
27-
);
28-
29-
/**
30-
* @dev Specialization of {AccountCore-_signableUserOpHash} that returns a typehash following EIP-712 typed data
31-
* hashing for readability. This assumes the underlying signature scheme implements `signTypedData`, which will be
32-
* the case when combined with {SignerECDSA} or {SignerERC7702}.
33-
*/
34-
function _signableUserOpHash(
35-
PackedUserOperation calldata userOp,
36-
bytes32 /*userOpHash*/
37-
) internal view virtual override returns (bytes32) {
38-
return
39-
_hashTypedDataV4(
40-
keccak256(
41-
abi.encode(
42-
PACKED_USER_OPERATION,
43-
userOp.sender,
44-
userOp.nonce,
45-
keccak256(userOp.initCode),
46-
keccak256(userOp.callData),
47-
userOp.accountGasLimits,
48-
userOp.preVerificationGas,
49-
userOp.gasFees,
50-
keccak256(userOp.paymasterAndData)
51-
)
52-
)
53-
);
54-
}
55-
}
22+
abstract contract Account is AccountCore, ERC721Holder, ERC1155Holder, ERC7739 {}

contracts/account/AccountCore.sol

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ abstract contract AccountCore is AbstractSigner, IAccount {
4747
* @dev Canonical entry point for the account that forwards and validates user operations.
4848
*/
4949
function entryPoint() public view virtual returns (IEntryPoint) {
50-
return ERC4337Utils.ENTRYPOINT_V07;
50+
return ERC4337Utils.ENTRYPOINT_V08;
5151
}
5252

5353
/**
@@ -95,14 +95,15 @@ abstract contract AccountCore is AbstractSigner, IAccount {
9595
}
9696

9797
/**
98-
* @dev Virtual function that returns the signable hash for a user operations. Some implementation may return
99-
* `userOpHash` while other may prefer a signer-friendly value such as an EIP-712 hash describing the `userOp`
100-
* details.
98+
* @dev Virtual function that returns the signable hash for a user operations. Since v0.8.0 of the entrypoint,
99+
* `userOpHash` is an EIP-712 hash that can be signed directly.
101100
*/
102101
function _signableUserOpHash(
103-
PackedUserOperation calldata userOp,
102+
PackedUserOperation calldata /*userOp*/,
104103
bytes32 userOpHash
105-
) internal view virtual returns (bytes32);
104+
) internal view virtual returns (bytes32) {
105+
return userOpHash;
106+
}
106107

107108
/**
108109
* @dev Sends the missing funds for executing the user operation to the {entrypoint}.

contracts/account/paymaster/PaymasterCore.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ abstract contract PaymasterCore is IPaymaster {
3838

3939
/// @dev Canonical entry point for the account that forwards and validates user operations.
4040
function entryPoint() public view virtual returns (IEntryPoint) {
41-
return ERC4337Utils.ENTRYPOINT_V07;
41+
return ERC4337Utils.ENTRYPOINT_V08;
4242
}
4343

4444
/// @inheritdoc IPaymaster

contracts/mocks/account/AccountERC7579HookedMock.sol

Lines changed: 0 additions & 41 deletions
This file was deleted.

contracts/mocks/account/AccountERC7579Mock.sol

Lines changed: 6 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,40 +2,18 @@
22

33
pragma solidity ^0.8.24;
44

5-
import {EIP712} from "@openzeppelin/contracts/utils/cryptography/EIP712.sol";
6-
import {PackedUserOperation} from "@openzeppelin/contracts/interfaces/draft-IERC4337.sol";
75
import {MODULE_TYPE_VALIDATOR} from "@openzeppelin/contracts/interfaces/draft-IERC7579.sol";
86
import {AccountERC7579} from "../../account/extensions/AccountERC7579.sol";
7+
import {AccountERC7579Hooked} from "../../account/extensions/AccountERC7579Hooked.sol";
98

10-
abstract contract AccountERC7579Mock is EIP712, AccountERC7579 {
11-
bytes32 internal constant _PACKED_USER_OPERATION =
12-
keccak256(
13-
"PackedUserOperation(address sender,uint256 nonce,bytes initCode,bytes callData,bytes32 accountGasLimits,uint256 preVerificationGas,bytes32 gasFees,bytes paymasterAndData)"
14-
);
15-
9+
abstract contract AccountERC7579Mock is AccountERC7579 {
1610
constructor(address validator, bytes memory initData) {
1711
_installModule(MODULE_TYPE_VALIDATOR, validator, initData);
1812
}
13+
}
1914

20-
function _signableUserOpHash(
21-
PackedUserOperation calldata userOp,
22-
bytes32 /*userOpHash*/
23-
) internal view virtual override returns (bytes32) {
24-
return
25-
_hashTypedDataV4(
26-
keccak256(
27-
abi.encode(
28-
_PACKED_USER_OPERATION,
29-
userOp.sender,
30-
userOp.nonce,
31-
keccak256(userOp.initCode),
32-
keccak256(userOp.callData),
33-
userOp.accountGasLimits,
34-
userOp.preVerificationGas,
35-
userOp.gasFees,
36-
keccak256(userOp.paymasterAndData)
37-
)
38-
)
39-
);
15+
abstract contract AccountERC7579HookedMock is AccountERC7579Hooked {
16+
constructor(address validator, bytes memory initData) {
17+
_installModule(MODULE_TYPE_VALIDATOR, validator, initData);
4018
}
4119
}

lib/@openzeppelin-contracts

package-lock.json

Lines changed: 8 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/account/Account.behavior.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ function shouldBehaveLikeAccountCore() {
1010
describe('entryPoint', function () {
1111
it('should return the canonical entrypoint', async function () {
1212
await this.mock.deploy();
13-
await expect(this.mock.entryPoint()).to.eventually.equal(entrypoint);
13+
await expect(this.mock.entryPoint()).to.eventually.equal(entrypoint.v08);
1414
});
1515
});
1616

@@ -32,7 +32,7 @@ function shouldBehaveLikeAccountCore() {
3232

3333
describe('when the caller is the canonical entrypoint', function () {
3434
beforeEach(async function () {
35-
this.mockFromEntrypoint = this.mock.connect(await impersonate(entrypoint.target));
35+
this.mockFromEntrypoint = this.mock.connect(await impersonate(entrypoint.v08.target));
3636
});
3737

3838
it('should return SIG_VALIDATION_SUCCESS if the signature is valid', async function () {
@@ -61,7 +61,7 @@ function shouldBehaveLikeAccountCore() {
6161

6262
await expect(
6363
this.mockFromEntrypoint.validateUserOp(operation.packed, operation.hash(), value),
64-
).to.changeEtherBalances([this.mock, entrypoint], [-value, value]);
64+
).to.changeEtherBalances([this.mock, entrypoint.v08], [-value, value]);
6565
});
6666
});
6767
});

test/account/Account.test.js

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
const { ethers } = require('hardhat');
1+
const { ethers, entrypoint } = require('hardhat');
22
const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers');
3+
4+
const { getDomain } = require('@openzeppelin/contracts/test/helpers/eip712');
35
const { ERC4337Helper } = require('../helpers/erc4337');
46
const { PackedUserOperation } = require('../helpers/eip712-types');
57
const { NonNativeSigner } = require('../helpers/signers');
@@ -18,23 +20,25 @@ async function fixture() {
1820

1921
// ERC-4337 account
2022
const helper = new ERC4337Helper();
21-
const env = await helper.wait();
2223
const mock = await helper.newAccount('$AccountMock', ['Account', '1']);
2324

25+
// ERC-4337 Entrypoint domain
26+
const entrypointDomain = await getDomain(entrypoint.v08);
27+
2428
// domain cannot be fetched using getDomain(mock) before the mock is deployed
2529
const domain = {
2630
name: 'Account',
2731
version: '1',
28-
chainId: env.chainId,
32+
chainId: entrypointDomain.chainId,
2933
verifyingContract: mock.address,
3034
};
3135

3236
const signUserOp = async userOp =>
3337
signer
34-
.signTypedData(domain, { PackedUserOperation }, userOp.packed)
38+
.signTypedData(entrypointDomain, { PackedUserOperation }, userOp.packed)
3539
.then(signature => Object.assign(userOp, { signature }));
3640

37-
return { ...env, mock, domain, signer, target, beneficiary, other, signUserOp };
41+
return { helper, mock, domain, signer, target, beneficiary, other, signUserOp };
3842
}
3943

4044
describe('Account', function () {

0 commit comments

Comments
 (0)