Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Use gasLimitNoBuffer on network fee estimation #29502

Merged
merged 21 commits into from
Jan 20, 2025
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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@
"@metamask/snaps-sdk": "^6.15.0",
"@metamask/snaps-utils": "^8.8.0",
"@metamask/solana-wallet-snap": "^1.0.4",
"@metamask/transaction-controller": "^42.1.0",
"@metamask/transaction-controller": "^43.0.0",
"@metamask/user-operation-controller": "^21.0.0",
"@metamask/utils": "^10.0.1",
"@ngraveio/bc-ur": "^1.1.12",
Expand Down
17 changes: 11 additions & 6 deletions shared/modules/gas.utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,7 @@ export function getMaximumGasTotalInHexWei({
* transaction will cost. For gasPrice types this is the same as max.
*
* @param {object} options - gas fee parameters object
* @param {string} [options.gasLimit] - the maximum amount of gas to allow this
* transaction to consume. Value is a hex string
* @param {string} [options.gasLimitNoBuffer] - gas limit without buffer
* @param {string} [options.gasPrice] - The fee in wei to pay per gas used.
* gasPrice is only set on Legacy type transactions. Value is hex string
* @param {string} [options.maxFeePerGas] - The maximum fee in wei to pay per
Expand All @@ -58,7 +57,7 @@ export function getMaximumGasTotalInHexWei({
* @returns {string} The minimum total cost of transaction in hex wei string
*/
export function getMinimumGasTotalInHexWei({
gasLimit = '0x0',
gasLimitNoBuffer = '0x0',
gasPrice,
maxPriorityFeePerGas,
maxFeePerGas,
Expand Down Expand Up @@ -91,16 +90,22 @@ export function getMinimumGasTotalInHexWei({
);
}
if (isEIP1559Estimate === false) {
return getMaximumGasTotalInHexWei({ gasLimit, gasPrice });
return getMaximumGasTotalInHexWei({
gasLimit: gasLimitNoBuffer,
gasPrice,
});
}
const minimumFeePerGas = new Numeric(baseFeePerGas, 16)
.add(new Numeric(maxPriorityFeePerGas, 16))
.toString();

if (new Numeric(minimumFeePerGas, 16).greaterThan(maxFeePerGas, 16)) {
return getMaximumGasTotalInHexWei({ gasLimit, maxFeePerGas });
return getMaximumGasTotalInHexWei({
gasLimit: gasLimitNoBuffer,
maxFeePerGas,
});
}
return new Numeric(gasLimit, 16)
return new Numeric(gasLimitNoBuffer, 16)
.times(new Numeric(minimumFeePerGas, 16))
.toPrefixedHexString();
}
4 changes: 2 additions & 2 deletions shared/modules/gas.utils.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ describe('gas utils', () => {
const gasLimitHex = addHexPrefix(gasLimit.toString(16));
const result = new Numeric(
getMinimumGasTotalInHexWei({
gasLimit: gasLimitHex,
gasLimitNoBuffer: gasLimitHex,
maxFeePerGas: addHexPrefix(maxFeePerGas.toString(16)),
maxPriorityFeePerGas: addHexPrefix(
maxPriorityFeePerGas.toString(16),
Expand Down Expand Up @@ -117,7 +117,7 @@ describe('gas utils', () => {
expect(
new Numeric(
getMinimumGasTotalInHexWei({
gasLimit: gasLimitHex,
gasLimitNoBuffer: gasLimitHex,
gasPrice: addHexPrefix(gasPrice.toString(16)),
}),
16,
Expand Down
1 change: 1 addition & 0 deletions test/data/confirmations/contract-interaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ export const genUnapprovedContractInteractionConfirmation = ({
to: '0x88aa6343307ec9a652ccddda3646e62b2f1a5125',
value: '0x3782dace9d900000',
},
gasLimitNoBuffer: '0xab77',
type: TransactionType.contractInteraction,
userEditedGasLimit: false,
userFeeLevel: 'medium',
Expand Down
1 change: 1 addition & 0 deletions test/data/confirmations/set-approval-for-all.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,6 @@ export const genUnapprovedSetApprovalForAllConfirmation = ({
maxFeePerGas: '0x5b06b0c0d',
maxPriorityFeePerGas: '0x59682f00',
},
gasLimitNoBuffer: '0x16a92',
type: TransactionType.tokenMethodSetApprovalForAll,
});
1 change: 1 addition & 0 deletions test/data/confirmations/token-approve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,6 @@ export const genUnapprovedApproveConfirmation = ({
maxFeePerGas: '0x5b06b0c0d',
maxPriorityFeePerGas: '0x59682f00',
},
gasLimitNoBuffer: '0x16a92',
type: TransactionType.tokenMethodApprove,
});
1 change: 1 addition & 0 deletions test/data/confirmations/token-transfer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export const genUnapprovedTokenTransferConfirmation = ({
maxFeePerGas: '0x5b06b0c0d',
maxPriorityFeePerGas: '0x59682f00',
},
gasLimitNoBuffer: '0x16a92',
type: TransactionType.tokenMethodTransfer,
origin: isWalletInitiatedConfirmation
? 'metamask'
Expand Down
7 changes: 7 additions & 0 deletions test/data/mock-state.json
Original file line number Diff line number Diff line change
Expand Up @@ -1150,6 +1150,7 @@
"gas": "0x5208",
"gasPrice": "0x3b9aca00"
},
"gasLimitNoBuffer": "0x5208",
"history": [
{
"id": 8393540981007587,
Expand Down Expand Up @@ -1199,6 +1200,7 @@
"gasPrice": "0x3b9aca00",
"nonce": "0xb5"
},
"gasLimitNoBuffer": "0xcf08",
"history": [
{
"id": 3387511061307736,
Expand Down Expand Up @@ -1331,6 +1333,7 @@
"gasPrice": "0x3b9aca00",
"nonce": "0xb6"
},
"gasLimitNoBuffer": "0xcf08",
"history": [
{
"id": 3387511061307737,
Expand Down Expand Up @@ -1463,6 +1466,7 @@
"gasPrice": "0x12a05f200",
"nonce": "0xb7"
},
"gasLimitNoBuffer": "0xcf08",
"history": [
{
"id": 3387511061307738,
Expand Down Expand Up @@ -1596,6 +1600,7 @@
"gas": "0x6169e",
"nonce": "0xb8"
},
"gasLimitNoBuffer": "0x6169e",
"history": [
{
"id": 3387511061307739,
Expand Down Expand Up @@ -1733,6 +1738,7 @@
"gasPrice": "0x3b9aca00",
"nonce": "0xb9"
},
"gasLimitNoBuffer": "0xd508",
"history": [
{
"id": 3387511061307740,
Expand Down Expand Up @@ -1865,6 +1871,7 @@
"gasPrice": "0x3b9aca00",
"gas": "0x5208"
},
"gasLimitNoBuffer": "0x5208",
"history": [
{
"id": 3387511061307741,
Expand Down
4 changes: 2 additions & 2 deletions test/e2e/tests/transaction/edit-gas-fee.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,12 +131,12 @@ describe('Editing Confirm Transaction', function () {
// has correct updated value on the confirm screen the transaction
await driver.waitForSelector({
css: '[data-testid="first-gas-field"]',
text: '0.0008 ETH',
text: '0.0002 ETH',
});

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

// confirms the transaction
Expand Down
8 changes: 4 additions & 4 deletions test/e2e/tests/transaction/send-edit.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,12 @@ describe('Editing Confirm Transaction', function () {
// has correct updated value on the confirm screen the transaction
await driver.findElement({
css: '[data-testid="first-gas-field"]',
text: '0.0008 ETH',
text: '0.0002 ETH',
});

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

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

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

// confirms the transaction
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export const getUnapprovedContractInteractionTransaction = (
maxFeePerGas: '0x5b06b0c0d',
maxPriorityFeePerGas: '0x59682f00',
},
gasLimitNoBuffer: '0x16a92',
userEditedGasLimit: false,
verifiedOnBlockchain: false,
type: TransactionType.contractInteraction,
Expand Down
1 change: 1 addition & 0 deletions test/integration/data/transaction-helpers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export const getUnapprovedTransaction = (
maxFeePerGas: '0x5b06b0c0d',
maxPriorityFeePerGas: '0x59682f00',
},
gasLimitNoBuffer: '0x16a92',
userEditedGasLimit: false,
verifiedOnBlockchain: false,
type: TransactionType.contractInteraction,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ describe('ConfirmGasDisplay', () => {
txParams: {
gas: '0x5208',
},
gasLimitNoBuffer: '0x5208',
userFeeLevel: 'medium',
},
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,37 @@ describe('useFeeCalculations', () => {
`);
});

it('picks up gasLimitNoBuffer for minimum network fee on estimations', () => {
const transactionMeta = genUnapprovedContractInteractionConfirmation({
address: CONTRACT_INTERACTION_SENDER_ADDRESS,
}) as TransactionMeta;

// txParams.gas is 0xab77
transactionMeta.gasLimitNoBuffer = '0x9b77';

const { result } = renderHookWithProvider(
() => useFeeCalculations(transactionMeta),
mockState,
);

expect(result.current).toMatchInlineSnapshot(`
{
"estimatedFeeFiat": "$0.03",
"estimatedFeeFiatWith18SignificantDigits": null,
"estimatedFeeNative": "0.0001 ETH",
"l1FeeFiat": "",
"l1FeeFiatWith18SignificantDigits": "",
"l1FeeNative": "",
"l2FeeFiat": "",
"l2FeeFiatWith18SignificantDigits": "",
"l2FeeNative": "",
"maxFeeFiat": "$0.07",
"maxFeeFiatWith18SignificantDigits": null,
"maxFeeNative": "0.0001 ETH",
}
`);
});

it('returns the correct estimate for a transaction with layer1GasFee', () => {
const transactionMeta = genUnapprovedContractInteractionConfirmation({
address: CONTRACT_INTERACTION_SENDER_ADDRESS,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,9 +157,10 @@ export function useFeeCalculations(transactionMeta: TransactionMeta) {
minimumFeePerGas = decimalToHex(maxFeePerGas);
}

const gasLimitNoBuffer = transactionMeta.gasLimitNoBuffer || HEX_ZERO;
const estimatedFee = multiplyHexes(
supportsEIP1559 ? (minimumFeePerGas as Hex) : (gasPrice as Hex),
gasLimit as Hex,
gasLimitNoBuffer as Hex,
);

return getFeesFromHex(estimatedFee);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const sendEther = {
userEditedGasLimit: false,
chainId: '0x5',
loadingDefaults: false,
gasLimitNoBuffer: '0x5208',
dappSuggestedGasFees: {
maxPriorityFeePerGas: '0x3b9aca00',
maxFeePerGas: '0x2540be400',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ const baseStore = {
txParams: { ...mockTxParams },
status: 'unapproved',
simulationData: {},
gasLimitNoBuffer: '0x5208',
},
],
gasEstimateType: GasEstimateTypes.legacy,
Expand Down Expand Up @@ -181,6 +182,7 @@ const baseStore = {
type: 'simpleSend',
history: [],
userFeeLevel: 'medium',
gasLimitNoBuffer: '0x5208',
defaultGasEstimates: {
estimateType: 'medium',
gas: '0x5208',
Expand Down
1 change: 1 addition & 0 deletions ui/pages/confirmations/hooks/useGasEstimates.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ export function useGasEstimates({
// gas fees.
let gasSettings = {
gasLimit: decimalToHex(gasLimit),
gasLimitNoBuffer: transaction?.gasLimitNoBuffer,
};
if (supportsEIP1559) {
gasSettings = {
Expand Down
9 changes: 6 additions & 3 deletions ui/pages/confirmations/hooks/useGasEstimates.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@ jest.mock('react-redux', () => {

const useGasEstimatesHook = (props) =>
useGasEstimates({
transaction: { txParams: { type: '0x2', value: '100' } },
transaction: {
gasLimitNoBuffer: '0x5208',
txParams: { type: '0x2', value: '100' },
},
gasLimit: '21000',
gasPrice: '10',
maxPriorityFeePerGas: '10',
Expand Down Expand Up @@ -68,7 +71,7 @@ describe('useGasEstimates', () => {
);
const minimumHexValue = getMinimumGasTotalInHexWei({
baseFeePerGas: decGWEIToHexWEI(estimatedBaseFee),
gasLimit: decimalToHex(gasLimit),
gasLimitNoBuffer: decimalToHex(gasLimit),
maxFeePerGas: decGWEIToHexWEI(maxFeePerGas),
maxPriorityFeePerGas: decGWEIToHexWEI(maxPriorityFeePerGas),
});
Expand Down Expand Up @@ -107,7 +110,7 @@ describe('useGasEstimates', () => {
}),
);
const minimumHexValue = getMinimumGasTotalInHexWei({
gasLimit: decimalToHex(gasLimit),
gasLimitNoBuffer: decimalToHex(gasLimit),
gasPrice: decGWEIToHexWEI(gasPrice),
});

Expand Down
1 change: 1 addition & 0 deletions ui/pages/confirmations/hooks/useGasFeeInputs.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ describe('useGasFeeInputs', () => {
...mockTransaction.txParams,
gas: '0x5208',
},
gasLimitNoBuffer: '0x5208',
}),
);
expect(result.current.balanceError).toBe(true);
Expand Down
1 change: 1 addition & 0 deletions ui/selectors/confirm-transaction.js
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ export const transactionFeeSelector = function (state, txData) {

const gasEstimationObject = {
gasLimit: txData.txParams?.gas ?? '0x0',
gasLimitNoBuffer: txData.gasLimitNoBuffer,
};

if (networkAndAccountSupportsEIP1559) {
Expand Down
Loading
Loading