Skip to content

Commit 40345e7

Browse files
committed
Merge remote-tracking branch 'origin/main' into bump-dependencies-13-03-2024
2 parents ab843c0 + 2278cb7 commit 40345e7

File tree

8 files changed

+162
-152
lines changed

8 files changed

+162
-152
lines changed

packages/user-operation-controller/src/UserOperationController.test.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -826,6 +826,42 @@ describe('UserOperationController', () => {
826826
expect(prepareMock).toHaveBeenCalledTimes(1);
827827
});
828828

829+
it('uses gas limits suggested by smart contract account during #addPaymasterData', async () => {
830+
const controller = new UserOperationController(optionsMock);
831+
const UPDATE_USER_OPERATION_WITH_GAS_LIMITS_RESPONSE_MOCK: UpdateUserOperationResponse =
832+
{
833+
paymasterAndData: '0xA',
834+
callGasLimit: '0x123',
835+
preVerificationGas: '0x456',
836+
verificationGasLimit: '0x789',
837+
};
838+
smartContractAccount.updateUserOperation.mockResolvedValue(
839+
UPDATE_USER_OPERATION_WITH_GAS_LIMITS_RESPONSE_MOCK,
840+
);
841+
const { id, hash } = await addUserOperation(
842+
controller,
843+
ADD_USER_OPERATION_REQUEST_MOCK,
844+
{ ...ADD_USER_OPERATION_OPTIONS_MOCK, smartContractAccount },
845+
);
846+
847+
await hash();
848+
849+
expect(Object.keys(controller.state.userOperations)).toHaveLength(1);
850+
expect(
851+
controller.state.userOperations[id].userOperation.callGasLimit,
852+
).toBe(UPDATE_USER_OPERATION_WITH_GAS_LIMITS_RESPONSE_MOCK.callGasLimit);
853+
expect(
854+
controller.state.userOperations[id].userOperation.verificationGasLimit,
855+
).toBe(
856+
UPDATE_USER_OPERATION_WITH_GAS_LIMITS_RESPONSE_MOCK.verificationGasLimit,
857+
);
858+
expect(
859+
controller.state.userOperations[id].userOperation.preVerificationGas,
860+
).toBe(
861+
UPDATE_USER_OPERATION_WITH_GAS_LIMITS_RESPONSE_MOCK.preVerificationGas,
862+
);
863+
});
864+
829865
describe('if approval request resolved with updated transaction', () => {
830866
it('updates gas fees without regeneration if paymaster data not set', async () => {
831867
const controller = new UserOperationController(optionsMock);

packages/user-operation-controller/src/UserOperationController.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,15 @@ export class UserOperationController extends BaseController<
538538
validateUpdateUserOperationResponse(response);
539539

540540
userOperation.paymasterAndData = response.paymasterAndData ?? EMPTY_BYTES;
541+
if (response.callGasLimit) {
542+
userOperation.callGasLimit = response.callGasLimit;
543+
}
544+
if (response.preVerificationGas) {
545+
userOperation.preVerificationGas = response.preVerificationGas;
546+
}
547+
if (response.verificationGasLimit) {
548+
userOperation.verificationGasLimit = response.verificationGasLimit;
549+
}
541550

542551
this.#updateMetadata(metadata);
543552
}

packages/user-operation-controller/src/helpers/SnapSmartContractAccount.test.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ const PATCH_USER_OPERATION_RESPONSE_MOCK: Awaited<
6262
ReturnType<KeyringController['patchUserOperation']>
6363
> = {
6464
paymasterAndData: '0x123',
65+
callGasLimit: '0x444',
66+
verificationGasLimit: '0x555',
67+
preVerificationGas: '0x667',
6568
};
6669

6770
const SIGN_USER_OPERATION_RESPONSE_MOCK: Awaited<
@@ -235,6 +238,11 @@ describe('SnapSmartContractAccount', () => {
235238

236239
expect(response).toStrictEqual<UpdateUserOperationResponse>({
237240
paymasterAndData: PATCH_USER_OPERATION_RESPONSE_MOCK.paymasterAndData,
241+
callGasLimit: PATCH_USER_OPERATION_RESPONSE_MOCK.callGasLimit,
242+
preVerificationGas:
243+
PATCH_USER_OPERATION_RESPONSE_MOCK.preVerificationGas,
244+
verificationGasLimit:
245+
PATCH_USER_OPERATION_RESPONSE_MOCK.verificationGasLimit,
238246
});
239247

240248
expect(patchMock).toHaveBeenCalledTimes(1);
@@ -260,6 +268,9 @@ describe('SnapSmartContractAccount', () => {
260268

261269
expect(response).toStrictEqual<UpdateUserOperationResponse>({
262270
paymasterAndData: undefined,
271+
callGasLimit: undefined,
272+
preVerificationGas: undefined,
273+
verificationGasLimit: undefined,
263274
});
264275
});
265276
});

packages/user-operation-controller/src/helpers/SnapSmartContractAccount.ts

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -65,18 +65,22 @@ export class SnapSmartContractAccount implements SmartContractAccount {
6565
async updateUserOperation(
6666
request: UpdateUserOperationRequest,
6767
): Promise<UpdateUserOperationResponse> {
68-
const { userOperation } = request;
68+
const { userOperation, chainId } = request;
6969
const { sender } = userOperation;
7070

71-
const { paymasterAndData: responsePaymasterAndData } =
72-
await this.#messenger.call(
73-
'KeyringController:patchUserOperation',
74-
sender,
75-
userOperation,
76-
{
77-
chainId: request.chainId,
78-
},
79-
);
71+
const {
72+
paymasterAndData: responsePaymasterAndData,
73+
verificationGasLimit,
74+
preVerificationGas,
75+
callGasLimit,
76+
} = await this.#messenger.call(
77+
'KeyringController:patchUserOperation',
78+
sender,
79+
userOperation,
80+
{
81+
chainId,
82+
},
83+
);
8084

8185
const paymasterAndData =
8286
responsePaymasterAndData === EMPTY_BYTES
@@ -85,6 +89,9 @@ export class SnapSmartContractAccount implements SmartContractAccount {
8589

8690
return {
8791
paymasterAndData,
92+
verificationGasLimit,
93+
preVerificationGas,
94+
callGasLimit,
8895
};
8996
}
9097

packages/user-operation-controller/src/types.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,15 @@ export type UpdateUserOperationResponse = {
256256
* Not required if a paymaster is not sponsoring the transaction.
257257
*/
258258
paymasterAndData?: string;
259+
260+
/**
261+
* The final gas limits for the user operation suggested by the smart contract account.
262+
* The simulated gas limits may be different after the bundler estimates gas with the use
263+
* of the paymaster.
264+
*/
265+
callGasLimit?: string;
266+
preVerificationGas?: string;
267+
verificationGasLimit?: string;
259268
};
260269

261270
/**

packages/user-operation-controller/src/utils/validation.test.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,25 @@ describe('validation', () => {
432432
'paymasterAndData',
433433
'wrong type',
434434
123,
435-
'Expected a value of type `Hexadecimal String`, but received: `123`',
435+
'Expected a value of type `Hexadecimal String or 0x`, but received: `123`',
436+
],
437+
[
438+
'callGasLimit',
439+
'wrong type',
440+
123,
441+
'Expected a value of type `Hexadecimal String or 0x`, but received: `123`',
442+
],
443+
[
444+
'preVerificationGas',
445+
'wrong type',
446+
123,
447+
'Expected a value of type `Hexadecimal String or 0x`, but received: `123`',
448+
],
449+
[
450+
'verificationGasLimit',
451+
'wrong type',
452+
123,
453+
'Expected a value of type `Hexadecimal String or 0x`, but received: `123`',
436454
],
437455
])(
438456
'throws if %s is %s',

packages/user-operation-controller/src/utils/validation.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,11 +135,12 @@ export function validatePrepareUserOperationResponse(
135135
export function validateUpdateUserOperationResponse(
136136
response: UpdateUserOperationResponse,
137137
) {
138-
const HexOrEmptyBytes = defineHex();
139-
140138
const ValidResponse = optional(
141139
object({
142-
paymasterAndData: optional(HexOrEmptyBytes),
140+
paymasterAndData: optional(defineHexOrEmptyBytes()),
141+
callGasLimit: optional(defineHexOrEmptyBytes()),
142+
preVerificationGas: optional(defineHexOrEmptyBytes()),
143+
verificationGasLimit: optional(defineHexOrEmptyBytes()),
143144
}),
144145
);
145146

0 commit comments

Comments
 (0)