Skip to content

Commit 6d9143c

Browse files
committed
fix: 'sendTransactionWithDelegation' encodesspecified 'value' into resulting transaction args, resulting in failed transaction
1 parent 34fd9c9 commit 6d9143c

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
@@ -318,15 +318,20 @@ describe('erc7710RedeemDelegationAction', () => {
318318
],
319319
});
320320

321+
const { delegationManager } = args;
322+
321323
const expectedArgs = {
322-
...args,
323-
to: args.delegationManager,
324+
account,
325+
chain,
326+
to: delegationManager,
327+
// value is not passed to sendTransaction
324328
data: redeemDelegationCallData,
329+
// permissionsContext and delegationManager are not passed to sendTransaction
325330
};
326331

327-
expect(sendTransaction.calledOnceWithExactly(expectedArgs)).to.equal(
328-
true,
329-
);
332+
expect(sendTransaction.calledOnce).to.equal(true);
333+
334+
expect(sendTransaction.firstCall.args[0]).to.deep.equal(expectedArgs);
330335
});
331336

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

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

@@ -230,3 +231,54 @@ test('Bob attempts to call the increment function directly', async () => {
230231

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

0 commit comments

Comments
 (0)