Skip to content

Commit ffa1eb1

Browse files
patchy-the-botPatchy Bot
andauthored
Fix #142: SendUseroperationWithDelegation still references AccountMeta (#157)
* Replace accountMetadata with dependencies in ERC-7710 delegation actions * Remove undefined dependencies from sendUserOperationWithDelegation test * Replace remaining accountMetadata with dependencies in tests * Remove incorrectly added dependencies argument from test case Rename one remaining reference to `accountMetadata` to `dependencies` --------- Co-authored-by: Patchy Bot <patchy@localhost>
1 parent dbfa5e1 commit ffa1eb1

3 files changed

Lines changed: 41 additions & 46 deletions

File tree

packages/delegator-e2e/test/actions/erc7710sendUserOperationWithDelegation.test.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ test('Bob redeems the delegation in order to call increment() on the counter con
187187
expect(targetAddressBalance).toEqual(10n);
188188
});
189189

190-
test('Bob redeems the delegation, and deploys Alices smart account via accountMetadata', async () => {
190+
test('Bob redeems the delegation, and deploys Alices smart account via dependencies', async () => {
191191
await fundAddress(bobSmartAccount.address);
192192

193193
const counterContract = getContract({
@@ -222,7 +222,7 @@ test('Bob redeems the delegation, and deploys Alices smart account via accountMe
222222
},
223223
],
224224
...gasPrice,
225-
accountMetadata: [{ factory, factoryData }],
225+
dependencies: [{ factory, factoryData }],
226226
});
227227

228228
const receipt = await bundlerClient.waitForUserOperationReceipt({
@@ -236,7 +236,7 @@ test('Bob redeems the delegation, and deploys Alices smart account via accountMe
236236
expect(countAfter).toEqual(1n);
237237
});
238238

239-
test('Bob redeems the delegation, with account metadata, even though Alices account is already deployed', async () => {
239+
test('Bob redeems the delegation, with dependencies, even though Alices account is already deployed', async () => {
240240
await fundAddress(bobSmartAccount.address);
241241

242242
const counterContract = getContract({
@@ -273,7 +273,7 @@ test('Bob redeems the delegation, with account metadata, even though Alices acco
273273
},
274274
],
275275
...gasPrice,
276-
accountMetadata: [{ factory, factoryData }],
276+
dependencies: [{ factory, factoryData }],
277277
});
278278

279279
const receipt = await bundlerClient.waitForUserOperationReceipt({
@@ -287,7 +287,7 @@ test('Bob redeems the delegation, with account metadata, even though Alices acco
287287
expect(countAfter).toEqual(1n);
288288
});
289289

290-
test('Bob calls sendUserOperationWithDelegation with the same accountMetadata multiple times', async () => {
290+
test('Bob calls sendUserOperationWithDelegation with the same dependencies multiple times', async () => {
291291
await fundAddress(bobSmartAccount.address);
292292

293293
const { factory, factoryData } = await aliceSmartAccount.getFactoryArgs();
@@ -305,7 +305,7 @@ test('Bob calls sendUserOperationWithDelegation with the same accountMetadata mu
305305
},
306306
],
307307
...gasPrice,
308-
accountMetadata: [
308+
dependencies: [
309309
{ factory, factoryData },
310310
{ factory, factoryData },
311311
],
@@ -331,7 +331,7 @@ test('Bob calls sendUserOperationWithDelegation with the same accountMetadata mu
331331
expect(aliceSmartAccountBalance).toEqual(10n);
332332
});
333333

334-
// callData is disallowed, because if we attempt to re-encode with additional calls (ie accountMetadata)
334+
// callData is disallowed, because if we attempt to re-encode with additional calls (ie dependencies)
335335
// the inner call will be targetting a function on the smart account, which is likely attributed with
336336
// OnlyEntryPoint. Because it's calling from the smart account, it will fail.
337337
test.skip('Bob attempts to call sendUserOperationWithDelegation with callData specified', async () => {

packages/smart-accounts-kit/src/actions/erc7710RedeemDelegationAction.ts

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ export type SendUserOperationWithDelegationParameters<
111111
TAccount extends SmartAccount | undefined = SmartAccount | undefined,
112112
TAccountOverride extends SmartAccount | undefined = SmartAccount | undefined,
113113
> = SendUserOperationParameters<TAccount, TAccountOverride, DelegatedCall[]> & {
114-
accountMetadata?: { factory: Hex; factoryData: Hex }[];
114+
dependencies?: { factory: Hex; factoryData: Hex }[];
115115
calls: DelegatedCall[];
116116
publicClient: PublicClient<Transport, Chain>;
117117
};
@@ -145,7 +145,7 @@ export type SendUserOperationWithDelegationParameters<
145145
* delegationManager: '0x...',
146146
* },
147147
* ],
148-
* accountMetadata: [{ factory: '0x...', factoryData: '0x...' }], // Optional: for deploying accounts
148+
* dependencies: [{ factory: '0x...', factoryData: '0x...' }], // Optional: for deploying accounts
149149
* })
150150
*/
151151
export async function sendUserOperationWithDelegationAction<
@@ -158,7 +158,7 @@ export async function sendUserOperationWithDelegationAction<
158158
TAccountOverride
159159
>,
160160
) {
161-
if (parameters.accountMetadata) {
161+
if (parameters.dependencies) {
162162
const { publicClient } = parameters;
163163

164164
const includedAccountKeys: Record<Hex, boolean> = {};
@@ -171,29 +171,24 @@ export async function sendUserOperationWithDelegationAction<
171171

172172
const { SimpleFactory } = getSmartAccountsEnvironment(chainId);
173173

174-
const uniqueAccountMetadatas = parameters.accountMetadata.filter(
175-
(accountMetadata) => {
176-
if (!isAddressEqual(accountMetadata.factory, SimpleFactory)) {
177-
throw new Error(
178-
`Invalid accountMetadata: ${accountMetadata.factory} is not allowed.`,
179-
);
180-
}
181-
182-
// ensure that factory calls are not duplicated
183-
const accountKey = concat([
184-
accountMetadata.factory,
185-
accountMetadata.factoryData,
186-
]);
187-
const isDuplicate = includedAccountKeys[accountKey];
188-
189-
includedAccountKeys[accountKey] = true;
190-
return !isDuplicate;
191-
},
192-
);
174+
const uniqueDependencies = parameters.dependencies.filter((dependency) => {
175+
if (!isAddressEqual(dependency.factory, SimpleFactory)) {
176+
throw new Error(
177+
`Invalid dependency: ${dependency.factory} is not allowed.`,
178+
);
179+
}
180+
181+
// ensure that factory calls are not duplicated
182+
const accountKey = concat([dependency.factory, dependency.factoryData]);
183+
const isDuplicate = includedAccountKeys[accountKey];
184+
185+
includedAccountKeys[accountKey] = true;
186+
return !isDuplicate;
187+
});
193188

194189
const factoryCalls = (
195190
await Promise.all(
196-
uniqueAccountMetadatas.map(async ({ factory, factoryData }) => {
191+
uniqueDependencies.map(async ({ factory, factoryData }) => {
197192
const isDeployed = await publicClient
198193
.call({
199194
to: factory,

packages/smart-accounts-kit/test/actions/erc7710RedeemDelegationAction.test.ts

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ describe('erc7710RedeemDelegationAction', () => {
9797
);
9898
});
9999

100-
it('should append factory calls when accountMetadata is provided', async () => {
100+
it('should append factory calls when dependencies is provided', async () => {
101101
const bundlerClient = createBundlerClient({
102102
transport: custom({ request: mockBundlerRequest }),
103103
chain,
@@ -115,7 +115,7 @@ describe('erc7710RedeemDelegationAction', () => {
115115
},
116116
];
117117

118-
const accountMetadata = [
118+
const dependencies = [
119119
{
120120
factory: simpleFactoryAddress,
121121
factoryData: randomBytes(128),
@@ -129,7 +129,7 @@ describe('erc7710RedeemDelegationAction', () => {
129129
{
130130
publicClient,
131131
calls,
132-
accountMetadata,
132+
dependencies,
133133
};
134134

135135
await extendedBundlerClient.sendUserOperationWithDelegation(
@@ -140,21 +140,21 @@ describe('erc7710RedeemDelegationAction', () => {
140140
...sendUserOperationWithDelegationArgs,
141141
calls: [
142142
{
143-
to: accountMetadata[0]?.factory,
144-
data: accountMetadata[0]?.factoryData,
143+
to: dependencies[0]?.factory,
144+
data: dependencies[0]?.factoryData,
145145
value: 0n,
146146
},
147147
{
148-
to: accountMetadata[1]?.factory,
149-
data: accountMetadata[1]?.factoryData,
148+
to: dependencies[1]?.factory,
149+
data: dependencies[1]?.factoryData,
150150
value: 0n,
151151
},
152152
...calls,
153153
],
154154
});
155155
});
156156

157-
it('should throw an error when SimpleFactory is provided as accountMetadata factory', async () => {
157+
it('should throw an error when SimpleFactory is provided as dependencies factory', async () => {
158158
const bundlerClient = createBundlerClient({
159159
transport: custom({ request: mockBundlerRequest }),
160160
chain,
@@ -170,7 +170,7 @@ describe('erc7710RedeemDelegationAction', () => {
170170
},
171171
];
172172

173-
const accountMetadata = [
173+
const dependencies = [
174174
{
175175
factory: randomAddress(),
176176
factoryData: randomBytes(128),
@@ -181,10 +181,10 @@ describe('erc7710RedeemDelegationAction', () => {
181181
{
182182
publicClient,
183183
calls,
184-
accountMetadata,
184+
dependencies,
185185
};
186186

187-
const factoryAddress = accountMetadata[0]?.factory;
187+
const factoryAddress = dependencies[0]?.factory;
188188

189189
if (!factoryAddress) {
190190
throw new Error('factoryAddress is not set');
@@ -195,7 +195,7 @@ describe('erc7710RedeemDelegationAction', () => {
195195
sendUserOperationWithDelegationArgs,
196196
),
197197
).rejects.toThrow(
198-
`Invalid accountMetadata: ${factoryAddress} is not allowed.`,
198+
`Invalid dependency: ${factoryAddress} is not allowed.`,
199199
);
200200
});
201201

@@ -217,7 +217,7 @@ describe('erc7710RedeemDelegationAction', () => {
217217
},
218218
];
219219

220-
const accountMetadata = [
220+
const dependencies = [
221221
{
222222
factory: simpleFactoryAddress,
223223
factoryData: randomBytes(128),
@@ -238,16 +238,16 @@ describe('erc7710RedeemDelegationAction', () => {
238238
Chain
239239
>,
240240
calls,
241-
accountMetadata,
241+
dependencies,
242242
};
243243

244244
await extendedBundlerClient.sendUserOperationWithDelegation(
245245
sendUserOperationWithDelegationArgs,
246246
);
247247

248248
expect(mockPublicClient.call.firstCall.args[0]).to.deep.equal({
249-
to: accountMetadata[0]?.factory,
250-
data: accountMetadata[0]?.factoryData,
249+
to: dependencies[0]?.factory,
250+
data: dependencies[0]?.factoryData,
251251
});
252252

253253
expect(sendUserOperationStub.firstCall.args[0]).to.deep.equal({

0 commit comments

Comments
 (0)