Skip to content

Commit 41626fc

Browse files
authored
fix: 'sendTransactionWithDelegation' encodesspecified 'value' into resulting transaction args, resulting in failed transaction (#30)
1 parent 28eb39e commit 41626fc

3 files changed

Lines changed: 98 additions & 6 deletions

File tree

packages/delegation-toolkit/src/experimental/erc7710RedeemDelegationAction.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,15 @@ export async function sendTransactionWithDelegationAction<
7979
],
8080
});
8181

82+
const {
83+
value: _value,
84+
permissionsContext: _permissionsContext,
85+
delegationManager: _delegationManager,
86+
...rest
87+
} = args;
88+
8289
const hash = await client.sendTransaction({
83-
...args,
90+
...rest,
8491
to: args.delegationManager,
8592
data: calldata,
8693
} as unknown as SendTransactionParameters);

packages/delegation-toolkit/test/experimental/erc7710RedeemDelegationAction.test.ts

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -314,15 +314,20 @@ describe('erc7710RedeemDelegationAction', () => {
314314
],
315315
});
316316

317+
const { delegationManager } = args;
318+
317319
const expectedArgs = {
318-
...args,
319-
to: args.delegationManager,
320+
account,
321+
chain,
322+
to: delegationManager,
323+
// value is not passed to sendTransaction
320324
data: redeemDelegationCallData,
325+
// permissionsContext and delegationManager are not passed to sendTransaction
321326
};
322327

323-
expect(sendTransaction.calledOnceWithExactly(expectedArgs)).to.equal(
324-
true,
325-
);
328+
expect(sendTransaction.calledOnce).to.equal(true);
329+
330+
expect(sendTransaction.firstCall.args[0]).to.deep.equal(expectedArgs);
326331
});
327332

328333
it('should throw an error when `to` is not provided', async () => {
@@ -341,5 +346,33 @@ describe('erc7710RedeemDelegationAction', () => {
341346
'`to` is required. `sendTransactionWithDelegation` cannot be used to deploy contracts.',
342347
);
343348
});
349+
350+
it('should not encode the specified `value`, `permissionsContext` and `delegationManager` into the resulting transaction', async () => {
351+
const extendedWalletClient = walletClient.extend(erc7710WalletActions());
352+
353+
const sendTransaction = stub(walletClient, 'sendTransaction');
354+
355+
const args: SendTransactionWithDelegationParameters = {
356+
account,
357+
chain,
358+
to: randomAddress(),
359+
value: 100n,
360+
data: randomBytes(128),
361+
permissionsContext: randomBytes(128),
362+
delegationManager: randomAddress(),
363+
};
364+
365+
await extendedWalletClient.sendTransactionWithDelegation(args);
366+
367+
expect(sendTransaction.calledOnce).to.equal(true);
368+
const sendTransactionArgs = sendTransaction.firstCall.args[0];
369+
expect(sendTransactionArgs.value).to.equal(undefined);
370+
expect((sendTransactionArgs as any).permissionsContext).to.equal(
371+
undefined,
372+
);
373+
expect((sendTransactionArgs as any).delegationManager).to.equal(
374+
undefined,
375+
);
376+
});
344377
});
345378
});

packages/delegator-e2e/test/experimental/erc7710sendTransactionWithDelegation.test.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
deploySmartAccount,
66
publicClient,
77
fundAddress,
8+
randomAddress,
89
} from '../utils/helpers';
910
import { chain } from '../../src/config';
1011

@@ -233,3 +234,54 @@ test('Bob attempts to call the increment function directly', async () => {
233234

234235
expect(countAfter).toEqual(0n);
235236
});
237+
238+
test('Bob sends a native value transaction with delegation', async () => {
239+
await deploySmartAccount(aliceSmartAccount);
240+
241+
const allowance = 100n;
242+
const recipient = randomAddress();
243+
244+
const { DelegationManager: delegationManager } =
245+
aliceSmartAccount.environment;
246+
247+
const caveats = createCaveatBuilder(aliceSmartAccount.environment).addCaveat(
248+
'nativeTokenTransferAmount',
249+
allowance,
250+
);
251+
252+
const delegation = createDelegation({
253+
to: bob.address,
254+
from: aliceSmartAccount.address,
255+
caveats,
256+
});
257+
258+
const signedDelegation = {
259+
...delegation,
260+
signature: await aliceSmartAccount.signDelegation({ delegation }),
261+
};
262+
263+
const permissionsContext = encodeDelegations([signedDelegation]);
264+
265+
const bobWalletClient = createWalletClient({
266+
account: bob,
267+
transport,
268+
chain,
269+
}).extend(erc7710WalletActions());
270+
271+
await fundAddress(aliceSmartAccount.address, allowance);
272+
273+
const transactionHash = await bobWalletClient.sendTransactionWithDelegation({
274+
account: bob,
275+
chain,
276+
to: recipient,
277+
value: allowance,
278+
permissionsContext,
279+
delegationManager,
280+
});
281+
282+
await publicClient.waitForTransactionReceipt({ hash: transactionHash });
283+
284+
const balance = await publicClient.getBalance({ address: recipient });
285+
286+
expect(balance).toEqual(allowance);
287+
});

0 commit comments

Comments
 (0)