Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/transaction-controller/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Bump `@metamask/accounts-controller` from `^39.0.2` to `^39.0.3` ([#9231](https://github.com/MetaMask/core/pull/9231))

### Fixed

- Add explicit error when submitting a batch that requires EIP-7702 but the account or chain does not support it ([#9240](https://github.com/MetaMask/core/pull/9240))

## [68.1.1]

### Changed
Expand Down
42 changes: 42 additions & 0 deletions packages/transaction-controller/src/utils/batch.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,48 @@ describe('Batch Utils', () => {
).toBe(TransactionType.bridgeApproval);
});

it('throws if EIP-7702 is required but the account does not support it', async () => {
const publishBatchHook: jest.MockedFn<PublishBatchHook> = jest.fn();

doesAccountSupportEIP7702Mock.mockReturnValueOnce(false);

await expect(
addTransactionBatch({
...request,
publishBatchHook,
request: {
...request.request,
disableHook: true,
disableSequential: true,
},
}),
).rejects.toThrow('Account does not support EIP-7702');

expect(addTransactionMock).not.toHaveBeenCalled();
expect(publishBatchHook).not.toHaveBeenCalled();
});

it('throws if EIP-7702 is required but the chain does not support it', async () => {
const publishBatchHook: jest.MockedFn<PublishBatchHook> = jest.fn();

doesChainSupportEIP7702Mock.mockReturnValueOnce(false);

await expect(
addTransactionBatch({
...request,
publishBatchHook,
request: {
...request.request,
disableHook: true,
disableSequential: true,
},
}),
).rejects.toThrow('Chain does not support EIP-7702');

expect(addTransactionMock).not.toHaveBeenCalled();
expect(publishBatchHook).not.toHaveBeenCalled();
});

it('returns provided batch ID', async () => {
isAccountUpgradedToEIP7702Mock.mockResolvedValueOnce({
delegationAddress: undefined,
Expand Down
12 changes: 10 additions & 2 deletions packages/transaction-controller/src/utils/batch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@ export async function addTransactionBatch(
messenger,
request: transactionBatchRequest,
} = request;

const { disableHook, disable7702, disableSequential } =
transactionBatchRequest;

const sizeLimit = getBatchSizeLimit(messenger);

validateBatchRequest({
Expand All @@ -143,15 +147,19 @@ export async function addTransactionBatch(
transactionBatchRequest.from,
);

if (!transactionBatchRequest.disable7702 && accountCanUse7702) {
if (disableHook && disableSequential && !disable7702 && !accountCanUse7702) {
throw rpcErrors.internal('Account does not support EIP-7702');
}

if (!disable7702 && accountCanUse7702) {
try {
return await addTransactionBatchWith7702(request);
} catch (error: unknown) {
const isEIP7702NotSupportedError =
error instanceof JsonRpcError &&
error.message === 'Chain does not support EIP-7702';

if (!isEIP7702NotSupportedError) {
if (!isEIP7702NotSupportedError || (disableHook && disableSequential)) {
throw error;
}
}
Expand Down
4 changes: 4 additions & 0 deletions packages/transaction-pay-controller/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Bump `@metamask/assets-controllers` from `^109.2.1` to `^109.2.2` ([#9231](https://github.com/MetaMask/core/pull/9231))

### Fixed

- Require EIP-7702 for direct mUSD vault deposits and ensure transaction ID collection always stops after the batch attempt ([#9240](https://github.com/MetaMask/core/pull/9240))

## [23.14.0]

### Changed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,8 @@ describe('fiat-direct-musd', () => {
).rejects.toThrow('Missing nested transactions');
});

it('prefixes addTransactionBatch errors with Vault', async () => {
it('prefixes addTransactionBatch errors with Vault and stops collecting transaction IDs', async () => {
const endMock = jest.fn();
const callMock = jest.fn((action: string) => {
if (action === 'TransactionPayController:getAmountData') {
return Promise.resolve({
Expand All @@ -478,6 +479,7 @@ describe('fiat-direct-musd', () => {

throw new Error(`Unexpected action: ${action}`);
});
collectTransactionIdsMock.mockReturnValue({ end: endMock });

await expect(
submitDirectMusdVaultDeposit({
Expand All @@ -486,6 +488,7 @@ describe('fiat-direct-musd', () => {
transaction: TRANSACTION_MOCK,
}),
).rejects.toThrow('Vault: batch failed');
expect(endMock).toHaveBeenCalledTimes(1);
});

it('throws when no vault transactions are collected', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,8 @@ export async function submitDirectMusdVaultDeposit({

try {
await messenger.call('TransactionController:addTransactionBatch', {
disableHook: true,
disableSequential: true,
from: moneyAccountAddress,
isGasFeeSponsored: true,
isInternal: true,
Expand All @@ -306,10 +308,10 @@ export async function submitDirectMusdVaultDeposit({
});
} catch (error) {
throw prefixError(error, VAULT_ERROR_PREFIX);
} finally {
end();
}

end();

log('Submitted direct mUSD vault deposit', {
moneyAccountAddress,
nestedTransactionCount: nestedTransactions.length,
Expand Down
Loading