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/bridge-status-controller/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- Add isGasFeeSponsored field in transaction batch params ([#7064](https://github.com/MetaMask/core/pull/7064))

## [59.0.0]

### Changed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1252,6 +1252,7 @@ Array [
"disable7702": true,
"from": "0xaccount1",
"isGasFeeIncluded": false,
"isGasFeeSponsored": false,
"networkClientId": "arbitrum",
"origin": "metamask",
"requireApproval": false,
Expand Down Expand Up @@ -2952,6 +2953,7 @@ Array [
"disable7702": true,
"from": "0xaccount1",
"isGasFeeIncluded": false,
"isGasFeeSponsored": false,
"networkClientId": "arbitrum",
"origin": "metamask",
"requireApproval": false,
Expand Down
2 changes: 2 additions & 0 deletions packages/bridge-status-controller/src/utils/transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,7 @@ export const getAddTransactionBatchParams = async ({
feeData: { txFee },
gasIncluded,
gasIncluded7702,
gasSponsored,
},
sentAmount,
toTokenAmount,
Expand Down Expand Up @@ -393,6 +394,7 @@ export const getAddTransactionBatchParams = async ({
>[0] = {
disable7702,
isGasFeeIncluded: Boolean(gasIncluded7702),
isGasFeeSponsored: Boolean(gasSponsored),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Gas Sponsorship Not Reflected in Quote Response

The gasSponsored property is destructured from quoteResponse.quote but it's not included in the quoteResponse parameter type definition. Looking at the context, the function signature shows quoteResponse: Omit<QuoteResponse, 'approval' | 'trade'> & Partial<QuoteMetadata>, but gasSponsored is not part of the quote object's known structure based on the imports from @metamask/bridge-controller. This could result in gasSponsored being undefined and isGasFeeSponsored always being false, even when gas is actually sponsored.

Fix in Cursor Fix in Web

networkClientId,
requireApproval,
origin: 'metamask',
Expand Down
1 change: 1 addition & 0 deletions packages/transaction-controller/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added

- Calculate operator fee for OP stack networks and include it in `layer1GasFee` ([#6979](https://github.com/MetaMask/core/pull/6979))
- Add support for `isGasFeeSponsored` field in transaction batch and add transaction options ([#7064](https://github.com/MetaMask/core/pull/7064))

## [61.1.0]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1692,6 +1692,7 @@ describe('TransactionController', () => {
id: expect.any(String),
isFirstTimeInteraction: undefined,
isGasFeeIncluded: undefined,
isGasFeeSponsored: undefined,
nestedTransactions: undefined,
networkClientId: NETWORK_CLIENT_ID_MOCK,
origin: undefined,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1216,6 +1216,7 @@ export class TransactionController extends BaseController<
deviceConfirmedOn,
disableGasBuffer,
isGasFeeIncluded,
isGasFeeSponsored,
method,
nestedTransactions,
networkClientId,
Expand Down Expand Up @@ -1315,6 +1316,7 @@ export class TransactionController extends BaseController<
disableGasBuffer,
id: random(),
isGasFeeIncluded,
isGasFeeSponsored,
isFirstTimeInteraction: undefined,
nestedTransactions,
networkClientId,
Expand Down
6 changes: 6 additions & 0 deletions packages/transaction-controller/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1726,6 +1726,9 @@ export type TransactionBatchRequest = {
/** Whether MetaMask will be compensated for the gas fee by the transaction. */
isGasFeeIncluded?: boolean;

/** Whether MetaMask will sponsor the gas fee for the transaction. */
isGasFeeSponsored?: boolean;

/** ID of the network client to submit the transaction. */
networkClientId: NetworkClientId;

Expand Down Expand Up @@ -2061,6 +2064,9 @@ export type AddTransactionOptions = {
/** Whether MetaMask will be compensated for the gas fee by the transaction. */
isGasFeeIncluded?: boolean;

/** Whether MetaMask will sponsor the gas fee for the transaction. */
isGasFeeSponsored?: boolean;

/** RPC method that requested the transaction. */
method?: string;

Expand Down
27 changes: 27 additions & 0 deletions packages/transaction-controller/src/utils/batch.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -810,6 +810,33 @@ describe('Batch Utils', () => {
},
);

it.each([true, false])(
'passes isGasFeeSponsored flag (%s) through to addTransaction when provided (EIP-7702 path)',
async (isGasFeeSponsored) => {
isAccountUpgradedToEIP7702Mock.mockResolvedValueOnce({
delegationAddress: undefined,
isSupported: true,
});

addTransactionMock.mockResolvedValueOnce({
transactionMeta: TRANSACTION_META_MOCK,
result: Promise.resolve(''),
});

request.request.isGasFeeSponsored = isGasFeeSponsored;

await addTransactionBatch(request);

expect(addTransactionMock).toHaveBeenCalledTimes(1);
expect(addTransactionMock).toHaveBeenCalledWith(
expect.any(Object),
expect.objectContaining({
isGasFeeSponsored,
}),
);
},
);

describe('validates security', () => {
it('using transaction params', async () => {
isAccountUpgradedToEIP7702Mock.mockResolvedValueOnce({
Expand Down
1 change: 1 addition & 0 deletions packages/transaction-controller/src/utils/batch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,7 @@ async function addTransactionBatchWith7702(
const { result } = await addTransaction(txParams, {
batchId,
isGasFeeIncluded: userRequest.isGasFeeIncluded,
isGasFeeSponsored: userRequest.isGasFeeSponsored,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is only for EIP-7702 flow, do we also want want to pass it for the hook fallback via STX or sequentially?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The requirement is 7702 support from the chain to activate sponsorship. If 7702 is not supported by the chain then sponsorship cannot happen.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Current gas fees sponsored use case is only for EIP-7702 delegation flow.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor, is it worth asserting this is passed in one of the existing unit tests?

nestedTransactions,
networkClientId,
origin,
Expand Down
Loading