diff --git a/packages/transaction-controller/CHANGELOG.md b/packages/transaction-controller/CHANGELOG.md index d716191231..9a100c5da3 100644 --- a/packages/transaction-controller/CHANGELOG.md +++ b/packages/transaction-controller/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- Validate `gas` and `gasLimit` are hexadecimal strings ([#5093](https://github.com/MetaMask/core/pull/5093)) + ### Changed - Bump `@metamask/base-controller` from `^7.0.0` to `^7.1.0` ([#5079](https://github.com/MetaMask/core/pull/5079)) diff --git a/packages/transaction-controller/src/utils/validation.test.ts b/packages/transaction-controller/src/utils/validation.test.ts index 05c4f57e1b..8b6d65e5ee 100644 --- a/packages/transaction-controller/src/utils/validation.test.ts +++ b/packages/transaction-controller/src/utils/validation.test.ts @@ -1,6 +1,7 @@ import { rpcErrors } from '@metamask/rpc-errors'; import { TransactionEnvelopeType } from '../types'; +import type { TransactionParams } from '../types'; import { validateTxParams } from './validation'; describe('validation', () => { @@ -362,6 +363,60 @@ describe('validation', () => { } as any), ).not.toThrow(); }); + + it('throws if gasLimit is defined but not a valid hexadecimal', () => { + expect(() => + validateTxParams({ + from: '0x1678a085c290ebd122dc42cba69373b5953b831d', + to: '0xfbb5595c18ca76bab52d66188e4ca50c7d95f77a', + maxFeePerGas: '0x01', + gasLimit: 'zzzzz', + // TODO: Replace `any` with type + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } as any), + ).toThrow( + rpcErrors.invalidParams( + 'Invalid transaction params: gasLimit is not a valid hexadecimal. got: (zzzzz)', + ), + ); + expect(() => + validateTxParams({ + from: '0x1678a085c290ebd122dc42cba69373b5953b831d', + to: '0xfbb5595c18ca76bab52d66188e4ca50c7d95f77a', + maxFeePerGas: '0x01', + gasLimit: '0x0', + // TODO: Replace `any` with type + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } as any), + ).not.toThrow(); + }); + + it('throws if gas is defined but not a valid hexadecimal', () => { + expect(() => + validateTxParams({ + from: '0x1678a085c290ebd122dc42cba69373b5953b831d', + to: '0xfbb5595c18ca76bab52d66188e4ca50c7d95f77a', + maxFeePerGas: '0x01', + gas: 'zzzzz', + // TODO: Replace `any` with type + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } as unknown as TransactionParams), + ).toThrow( + rpcErrors.invalidParams( + 'Invalid transaction params: gas is not a valid hexadecimal. got: (zzzzz)', + ), + ); + expect(() => + validateTxParams({ + from: '0x1678a085c290ebd122dc42cba69373b5953b831d', + to: '0xfbb5595c18ca76bab52d66188e4ca50c7d95f77a', + maxFeePerGas: '0x01', + gas: '0x0', + // TODO: Replace `any` with type + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } as unknown as TransactionParams), + ).not.toThrow(); + }); }); }); }); diff --git a/packages/transaction-controller/src/utils/validation.ts b/packages/transaction-controller/src/utils/validation.ts index 3e725483fe..fbef756b31 100644 --- a/packages/transaction-controller/src/utils/validation.ts +++ b/packages/transaction-controller/src/utils/validation.ts @@ -7,7 +7,12 @@ import { isStrictHexString } from '@metamask/utils'; import { TransactionEnvelopeType, type TransactionParams } from '../types'; import { isEIP1559Transaction } from './utils'; -type GasFieldsToValidate = 'gasPrice' | 'maxFeePerGas' | 'maxPriorityFeePerGas'; +type GasFieldsToValidate = + | 'gasPrice' + | 'maxFeePerGas' + | 'maxPriorityFeePerGas' + | 'gas' + | 'gasLimit'; /** * Validates whether a transaction initiated by a specific 'from' address is permitted by the origin. @@ -281,6 +286,14 @@ function validateGasFeeParams(txParams: TransactionParams) { ); ensureFieldIsValidHex(txParams, 'maxPriorityFeePerGas'); } + + if (txParams.gasLimit) { + ensureFieldIsValidHex(txParams, 'gasLimit'); + } + + if (txParams.gas) { + ensureFieldIsValidHex(txParams, 'gas'); + } } /**