Skip to content

Commit 5887e05

Browse files
authored
feat: Use gasLimitNoBuffer on network fee estimation (#29502)
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> While estimating gas for the transaction we add `50%` gas limit buffer. With this PR we want to show network fee without gas limit buffer using `gasLimitNoBuffer` property on `transactionMeta`. [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/29502?quickstart=1) ## **Related issues** Fixes: MetaMask/MetaMask-planning#3773 ## **Manual testing steps** N/A ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> In the recording you will see that `gasLimitNoBuffer` used over `txParams.gas`. Please see that `txParams.gas` is greater than `gasLimitNoBuffer`. This calculation leads lower value in the UI. https://github.com/user-attachments/assets/b5726828-7c13-4eb4-83fa-eea21562e6a9 ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [X] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [X] I've completed the PR template to the best of my ability - [X] I’ve included tests if applicable - [X] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [X] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots.
1 parent 2751a0d commit 5887e05

22 files changed

+87
-27
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@
349349
"@metamask/snaps-sdk": "^6.15.0",
350350
"@metamask/snaps-utils": "^8.8.0",
351351
"@metamask/solana-wallet-snap": "^1.0.4",
352-
"@metamask/transaction-controller": "^42.1.0",
352+
"@metamask/transaction-controller": "^43.0.0",
353353
"@metamask/user-operation-controller": "^21.0.0",
354354
"@metamask/utils": "^10.0.1",
355355
"@ngraveio/bc-ur": "^1.1.12",

shared/modules/gas.utils.js

+11-6
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,7 @@ export function getMaximumGasTotalInHexWei({
4343
* transaction will cost. For gasPrice types this is the same as max.
4444
*
4545
* @param {object} options - gas fee parameters object
46-
* @param {string} [options.gasLimit] - the maximum amount of gas to allow this
47-
* transaction to consume. Value is a hex string
46+
* @param {string} [options.gasLimitNoBuffer] - gas limit without buffer
4847
* @param {string} [options.gasPrice] - The fee in wei to pay per gas used.
4948
* gasPrice is only set on Legacy type transactions. Value is hex string
5049
* @param {string} [options.maxFeePerGas] - The maximum fee in wei to pay per
@@ -58,7 +57,7 @@ export function getMaximumGasTotalInHexWei({
5857
* @returns {string} The minimum total cost of transaction in hex wei string
5958
*/
6059
export function getMinimumGasTotalInHexWei({
61-
gasLimit = '0x0',
60+
gasLimitNoBuffer = '0x0',
6261
gasPrice,
6362
maxPriorityFeePerGas,
6463
maxFeePerGas,
@@ -91,16 +90,22 @@ export function getMinimumGasTotalInHexWei({
9190
);
9291
}
9392
if (isEIP1559Estimate === false) {
94-
return getMaximumGasTotalInHexWei({ gasLimit, gasPrice });
93+
return getMaximumGasTotalInHexWei({
94+
gasLimit: gasLimitNoBuffer,
95+
gasPrice,
96+
});
9597
}
9698
const minimumFeePerGas = new Numeric(baseFeePerGas, 16)
9799
.add(new Numeric(maxPriorityFeePerGas, 16))
98100
.toString();
99101

100102
if (new Numeric(minimumFeePerGas, 16).greaterThan(maxFeePerGas, 16)) {
101-
return getMaximumGasTotalInHexWei({ gasLimit, maxFeePerGas });
103+
return getMaximumGasTotalInHexWei({
104+
gasLimit: gasLimitNoBuffer,
105+
maxFeePerGas,
106+
});
102107
}
103-
return new Numeric(gasLimit, 16)
108+
return new Numeric(gasLimitNoBuffer, 16)
104109
.times(new Numeric(minimumFeePerGas, 16))
105110
.toPrefixedHexString();
106111
}

shared/modules/gas.utils.test.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ describe('gas utils', () => {
4848
const gasLimitHex = addHexPrefix(gasLimit.toString(16));
4949
const result = new Numeric(
5050
getMinimumGasTotalInHexWei({
51-
gasLimit: gasLimitHex,
51+
gasLimitNoBuffer: gasLimitHex,
5252
maxFeePerGas: addHexPrefix(maxFeePerGas.toString(16)),
5353
maxPriorityFeePerGas: addHexPrefix(
5454
maxPriorityFeePerGas.toString(16),
@@ -117,7 +117,7 @@ describe('gas utils', () => {
117117
expect(
118118
new Numeric(
119119
getMinimumGasTotalInHexWei({
120-
gasLimit: gasLimitHex,
120+
gasLimitNoBuffer: gasLimitHex,
121121
gasPrice: addHexPrefix(gasPrice.toString(16)),
122122
}),
123123
16,

test/data/confirmations/contract-interaction.ts

+1
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ export const genUnapprovedContractInteractionConfirmation = ({
161161
to: '0x88aa6343307ec9a652ccddda3646e62b2f1a5125',
162162
value: '0x3782dace9d900000',
163163
},
164+
gasLimitNoBuffer: '0xab77',
164165
type: TransactionType.contractInteraction,
165166
userEditedGasLimit: false,
166167
userFeeLevel: 'medium',

test/data/confirmations/set-approval-for-all.ts

+1
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,6 @@ export const genUnapprovedSetApprovalForAllConfirmation = ({
2626
maxFeePerGas: '0x5b06b0c0d',
2727
maxPriorityFeePerGas: '0x59682f00',
2828
},
29+
gasLimitNoBuffer: '0x16a92',
2930
type: TransactionType.tokenMethodSetApprovalForAll,
3031
});

test/data/confirmations/token-approve.ts

+1
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,6 @@ export const genUnapprovedApproveConfirmation = ({
2525
maxFeePerGas: '0x5b06b0c0d',
2626
maxPriorityFeePerGas: '0x59682f00',
2727
},
28+
gasLimitNoBuffer: '0x16a92',
2829
type: TransactionType.tokenMethodApprove,
2930
});

test/data/confirmations/token-transfer.ts

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export const genUnapprovedTokenTransferConfirmation = ({
3030
maxFeePerGas: '0x5b06b0c0d',
3131
maxPriorityFeePerGas: '0x59682f00',
3232
},
33+
gasLimitNoBuffer: '0x16a92',
3334
type: TransactionType.tokenMethodTransfer,
3435
origin: isWalletInitiatedConfirmation
3536
? 'metamask'

test/data/mock-state.json

+7
Original file line numberDiff line numberDiff line change
@@ -1150,6 +1150,7 @@
11501150
"gas": "0x5208",
11511151
"gasPrice": "0x3b9aca00"
11521152
},
1153+
"gasLimitNoBuffer": "0x5208",
11531154
"history": [
11541155
{
11551156
"id": 8393540981007587,
@@ -1199,6 +1200,7 @@
11991200
"gasPrice": "0x3b9aca00",
12001201
"nonce": "0xb5"
12011202
},
1203+
"gasLimitNoBuffer": "0xcf08",
12021204
"history": [
12031205
{
12041206
"id": 3387511061307736,
@@ -1331,6 +1333,7 @@
13311333
"gasPrice": "0x3b9aca00",
13321334
"nonce": "0xb6"
13331335
},
1336+
"gasLimitNoBuffer": "0xcf08",
13341337
"history": [
13351338
{
13361339
"id": 3387511061307737,
@@ -1463,6 +1466,7 @@
14631466
"gasPrice": "0x12a05f200",
14641467
"nonce": "0xb7"
14651468
},
1469+
"gasLimitNoBuffer": "0xcf08",
14661470
"history": [
14671471
{
14681472
"id": 3387511061307738,
@@ -1596,6 +1600,7 @@
15961600
"gas": "0x6169e",
15971601
"nonce": "0xb8"
15981602
},
1603+
"gasLimitNoBuffer": "0x6169e",
15991604
"history": [
16001605
{
16011606
"id": 3387511061307739,
@@ -1733,6 +1738,7 @@
17331738
"gasPrice": "0x3b9aca00",
17341739
"nonce": "0xb9"
17351740
},
1741+
"gasLimitNoBuffer": "0xd508",
17361742
"history": [
17371743
{
17381744
"id": 3387511061307740,
@@ -1865,6 +1871,7 @@
18651871
"gasPrice": "0x3b9aca00",
18661872
"gas": "0x5208"
18671873
},
1874+
"gasLimitNoBuffer": "0x5208",
18681875
"history": [
18691876
{
18701877
"id": 3387511061307741,

test/e2e/tests/transaction/edit-gas-fee.spec.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -131,12 +131,12 @@ describe('Editing Confirm Transaction', function () {
131131
// has correct updated value on the confirm screen the transaction
132132
await driver.waitForSelector({
133133
css: '[data-testid="first-gas-field"]',
134-
text: '0.0008 ETH',
134+
text: '0.0002 ETH',
135135
});
136136

137137
await driver.waitForSelector({
138138
css: '[data-testid="native-currency"]',
139-
text: '$1.44',
139+
text: '$0.30',
140140
});
141141

142142
// confirms the transaction

test/e2e/tests/transaction/send-edit.spec.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,12 @@ describe('Editing Confirm Transaction', function () {
6464
// has correct updated value on the confirm screen the transaction
6565
await driver.findElement({
6666
css: '[data-testid="first-gas-field"]',
67-
text: '0.0008 ETH',
67+
text: '0.0002 ETH',
6868
});
6969

7070
await driver.findElement({
7171
css: '[data-testid="native-currency"]',
72-
text: '$1.36',
72+
text: '$0.29',
7373
});
7474

7575
// confirms the transaction
@@ -158,12 +158,12 @@ describe('Editing Confirm Transaction', function () {
158158
// has correct updated value on the confirm screen the transaction
159159
await driver.findElement({
160160
css: '[data-testid="first-gas-field"]',
161-
text: '0.0008 ETH',
161+
text: '0.0002 ETH',
162162
});
163163

164164
await driver.findElement({
165165
css: '[data-testid="native-currency"]',
166-
text: '$1.36',
166+
text: '$0.29',
167167
});
168168

169169
// confirms the transaction

test/integration/confirmations/transactions/transactionDataHelpers.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export const getUnapprovedContractInteractionTransaction = (
2525
maxFeePerGas: '0x5b06b0c0d',
2626
maxPriorityFeePerGas: '0x59682f00',
2727
},
28+
gasLimitNoBuffer: '0x16a92',
2829
userEditedGasLimit: false,
2930
verifiedOnBlockchain: false,
3031
type: TransactionType.contractInteraction,

test/integration/data/transaction-helpers.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export const getUnapprovedTransaction = (
2525
maxFeePerGas: '0x5b06b0c0d',
2626
maxPriorityFeePerGas: '0x59682f00',
2727
},
28+
gasLimitNoBuffer: '0x16a92',
2829
userEditedGasLimit: false,
2930
verifiedOnBlockchain: false,
3031
type: TransactionType.contractInteraction,

ui/pages/confirmations/components/confirm-gas-display/confirm-gas-display.test.js

+1
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ describe('ConfirmGasDisplay', () => {
7575
txParams: {
7676
gas: '0x5208',
7777
},
78+
gasLimitNoBuffer: '0x5208',
7879
userFeeLevel: 'medium',
7980
},
8081
});

ui/pages/confirmations/components/confirm/info/hooks/useFeeCalculations.test.ts

+31
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,37 @@ describe('useFeeCalculations', () => {
6565
`);
6666
});
6767

68+
it('picks up gasLimitNoBuffer for minimum network fee on estimations', () => {
69+
const transactionMeta = genUnapprovedContractInteractionConfirmation({
70+
address: CONTRACT_INTERACTION_SENDER_ADDRESS,
71+
}) as TransactionMeta;
72+
73+
// txParams.gas is 0xab77
74+
transactionMeta.gasLimitNoBuffer = '0x9b77';
75+
76+
const { result } = renderHookWithProvider(
77+
() => useFeeCalculations(transactionMeta),
78+
mockState,
79+
);
80+
81+
expect(result.current).toMatchInlineSnapshot(`
82+
{
83+
"estimatedFeeFiat": "$0.03",
84+
"estimatedFeeFiatWith18SignificantDigits": null,
85+
"estimatedFeeNative": "0.0001 ETH",
86+
"l1FeeFiat": "",
87+
"l1FeeFiatWith18SignificantDigits": "",
88+
"l1FeeNative": "",
89+
"l2FeeFiat": "",
90+
"l2FeeFiatWith18SignificantDigits": "",
91+
"l2FeeNative": "",
92+
"maxFeeFiat": "$0.07",
93+
"maxFeeFiatWith18SignificantDigits": null,
94+
"maxFeeNative": "0.0001 ETH",
95+
}
96+
`);
97+
});
98+
6899
it('returns the correct estimate for a transaction with layer1GasFee', () => {
69100
const transactionMeta = genUnapprovedContractInteractionConfirmation({
70101
address: CONTRACT_INTERACTION_SENDER_ADDRESS,

ui/pages/confirmations/components/confirm/info/hooks/useFeeCalculations.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -157,9 +157,10 @@ export function useFeeCalculations(transactionMeta: TransactionMeta) {
157157
minimumFeePerGas = decimalToHex(maxFeePerGas);
158158
}
159159

160+
const gasLimitNoBuffer = transactionMeta.gasLimitNoBuffer || HEX_ZERO;
160161
const estimatedFee = multiplyHexes(
161162
supportsEIP1559 ? (minimumFeePerGas as Hex) : (gasPrice as Hex),
162-
gasLimit as Hex,
163+
gasLimitNoBuffer as Hex,
163164
);
164165

165166
return getFeesFromHex(estimatedFee);

ui/pages/confirmations/confirm-send-ether/confirm-send-ether.test.js

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ const sendEther = {
3333
userEditedGasLimit: false,
3434
chainId: '0x5',
3535
loadingDefaults: false,
36+
gasLimitNoBuffer: '0x5208',
3637
dappSuggestedGasFees: {
3738
maxPriorityFeePerGas: '0x3b9aca00',
3839
maxFeePerGas: '0x2540be400',

ui/pages/confirmations/confirm-transaction-base/confirm-transaction-base.test.js

+2
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ const baseStore = {
9191
txParams: { ...mockTxParams },
9292
status: 'unapproved',
9393
simulationData: {},
94+
gasLimitNoBuffer: '0x5208',
9495
},
9596
],
9697
gasEstimateType: GasEstimateTypes.legacy,
@@ -181,6 +182,7 @@ const baseStore = {
181182
type: 'simpleSend',
182183
history: [],
183184
userFeeLevel: 'medium',
185+
gasLimitNoBuffer: '0x5208',
184186
defaultGasEstimates: {
185187
estimateType: 'medium',
186188
gas: '0x5208',

ui/pages/confirmations/hooks/useGasEstimates.js

+1
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ export function useGasEstimates({
6969
// gas fees.
7070
let gasSettings = {
7171
gasLimit: decimalToHex(gasLimit),
72+
gasLimitNoBuffer: transaction?.gasLimitNoBuffer,
7273
};
7374
if (supportsEIP1559) {
7475
gasSettings = {

ui/pages/confirmations/hooks/useGasEstimates.test.js

+6-3
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,10 @@ jest.mock('react-redux', () => {
3535

3636
const useGasEstimatesHook = (props) =>
3737
useGasEstimates({
38-
transaction: { txParams: { type: '0x2', value: '100' } },
38+
transaction: {
39+
gasLimitNoBuffer: '0x5208',
40+
txParams: { type: '0x2', value: '100' },
41+
},
3942
gasLimit: '21000',
4043
gasPrice: '10',
4144
maxPriorityFeePerGas: '10',
@@ -68,7 +71,7 @@ describe('useGasEstimates', () => {
6871
);
6972
const minimumHexValue = getMinimumGasTotalInHexWei({
7073
baseFeePerGas: decGWEIToHexWEI(estimatedBaseFee),
71-
gasLimit: decimalToHex(gasLimit),
74+
gasLimitNoBuffer: decimalToHex(gasLimit),
7275
maxFeePerGas: decGWEIToHexWEI(maxFeePerGas),
7376
maxPriorityFeePerGas: decGWEIToHexWEI(maxPriorityFeePerGas),
7477
});
@@ -107,7 +110,7 @@ describe('useGasEstimates', () => {
107110
}),
108111
);
109112
const minimumHexValue = getMinimumGasTotalInHexWei({
110-
gasLimit: decimalToHex(gasLimit),
113+
gasLimitNoBuffer: decimalToHex(gasLimit),
111114
gasPrice: decGWEIToHexWEI(gasPrice),
112115
});
113116

ui/pages/confirmations/hooks/useGasFeeInputs.test.js

+1
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ describe('useGasFeeInputs', () => {
185185
...mockTransaction.txParams,
186186
gas: '0x5208',
187187
},
188+
gasLimitNoBuffer: '0x5208',
188189
}),
189190
);
190191
expect(result.current.balanceError).toBe(true);

ui/selectors/confirm-transaction.js

+1
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ export const transactionFeeSelector = function (state, txData) {
216216

217217
const gasEstimationObject = {
218218
gasLimit: txData.txParams?.gas ?? '0x0',
219+
gasLimitNoBuffer: txData.gasLimitNoBuffer,
219220
};
220221

221222
if (networkAndAccountSupportsEIP1559) {

0 commit comments

Comments
 (0)