11import type { TypedTransaction } from '@ethereumjs/tx' ;
22import { TransactionFactory } from '@ethereumjs/tx' ;
3+ import { BigNumber } from '@ethersproject/bignumber' ;
34import { Contract } from '@ethersproject/contracts' ;
45import type { Provider } from '@metamask/network-controller' ;
56import type { Hex } from '@metamask/utils' ;
6-
7- import { OracleLayer1GasFeeFlow } from './OracleLayer1GasFeeFlow' ;
87import { CHAIN_IDS } from '../constants' ;
98import type { TransactionControllerMessenger } from '../TransactionController' ;
109import type { Layer1GasFeeFlowRequest , TransactionMeta } from '../types' ;
1110import { TransactionStatus } from '../types' ;
11+ import { OracleLayer1GasFeeFlow } from './OracleLayer1GasFeeFlow' ;
1212
1313jest . mock ( '@ethersproject/contracts' , ( ) => ( {
1414 Contract : jest . fn ( ) ,
@@ -36,7 +36,8 @@ const TRANSACTION_META_MOCK: TransactionMeta = {
3636
3737const SERIALIZED_TRANSACTION_MOCK = '0x1234' ;
3838const ORACLE_ADDRESS_MOCK = '0x5678' as Hex ;
39- const LAYER_1_FEE_MOCK = '0x9ABCD' ;
39+ const LAYER_1_FEE_MOCK = '0x09abcd' ;
40+ const OPERATOR_FEE_MOCK = '0x5' ;
4041const DEFAULT_GAS_PRICE_ORACLE_ADDRESS =
4142 '0x420000000000000000000000000000000000000F' ;
4243
@@ -98,9 +99,10 @@ class DefaultOracleLayer1GasFeeFlow extends OracleLayer1GasFeeFlow {
9899
99100describe ( 'OracleLayer1GasFeeFlow' , ( ) => {
100101 const contractMock = jest . mocked ( Contract ) ;
101- const contractGetL1FeeMock : jest . MockedFn <
102- ( ) => Promise < { toHexString : ( ) => string } >
103- > = jest . fn ( ) ;
102+ const contractGetL1FeeMock : jest . MockedFn < ( ) => Promise < BigNumber > > =
103+ jest . fn ( ) ;
104+ const contractGetOperatorFeeMock : jest . MockedFn < ( ) => Promise < BigNumber > > =
105+ jest . fn ( ) ;
104106
105107 let request : Layer1GasFeeFlowRequest ;
106108
@@ -112,13 +114,14 @@ describe('OracleLayer1GasFeeFlow', () => {
112114
113115 contractMock . mockClear ( ) ;
114116 contractGetL1FeeMock . mockClear ( ) ;
117+ contractGetOperatorFeeMock . mockClear ( ) ;
115118
116- contractGetL1FeeMock . mockResolvedValue ( {
117- toHexString : ( ) => LAYER_1_FEE_MOCK ,
118- } ) ;
119+ contractGetL1FeeMock . mockResolvedValue ( BigNumber . from ( LAYER_1_FEE_MOCK ) ) ;
120+ contractGetOperatorFeeMock . mockResolvedValue ( BigNumber . from ( 0 ) ) ;
119121
120122 contractMock . mockReturnValue ( {
121123 getL1Fee : contractGetL1FeeMock ,
124+ getOperatorFee : contractGetOperatorFeeMock ,
122125 } as unknown as Contract ) ;
123126 } ) ;
124127
@@ -156,6 +159,7 @@ describe('OracleLayer1GasFeeFlow', () => {
156159 expect ( contractGetL1FeeMock ) . toHaveBeenCalledWith (
157160 serializedTransactionMock ,
158161 ) ;
162+ expect ( contractGetOperatorFeeMock ) . not . toHaveBeenCalled ( ) ;
159163 } ) ;
160164
161165 it ( 'signs transaction with dummy key if supported by flow' , async ( ) => {
@@ -180,6 +184,7 @@ describe('OracleLayer1GasFeeFlow', () => {
180184 } ) ;
181185
182186 expect ( typedTransactionMock . sign ) . toHaveBeenCalledTimes ( 1 ) ;
187+ expect ( contractGetOperatorFeeMock ) . not . toHaveBeenCalled ( ) ;
183188 } ) ;
184189
185190 describe ( 'throws' , ( ) => {
@@ -228,5 +233,75 @@ describe('OracleLayer1GasFeeFlow', () => {
228233 expect ( oracleAddress ) . toBe ( DEFAULT_GAS_PRICE_ORACLE_ADDRESS ) ;
229234 expect ( typedTransactionMock . sign ) . not . toHaveBeenCalled ( ) ;
230235 } ) ;
236+
237+ it ( 'adds operator fee when gas used is available' , async ( ) => {
238+ const gasUsed = '0x5208' ;
239+ request = {
240+ ...request ,
241+ transactionMeta : {
242+ ...request . transactionMeta ,
243+ gasUsed,
244+ } ,
245+ } ;
246+
247+ contractGetOperatorFeeMock . mockResolvedValueOnce (
248+ BigNumber . from ( OPERATOR_FEE_MOCK ) ,
249+ ) ;
250+
251+ const flow = new MockOracleLayer1GasFeeFlow ( false ) ;
252+ const response = await flow . getLayer1Fee ( request ) ;
253+
254+ expect ( contractGetOperatorFeeMock ) . toHaveBeenCalledTimes ( 1 ) ;
255+ expect ( contractGetOperatorFeeMock ) . toHaveBeenCalledWith ( gasUsed ) ;
256+ expect ( response ) . toStrictEqual ( {
257+ layer1Fee : BigNumber . from ( LAYER_1_FEE_MOCK )
258+ . add ( BigNumber . from ( OPERATOR_FEE_MOCK ) )
259+ . toHexString ( ) ,
260+ } ) ;
261+ } ) ;
262+
263+ it ( 'defaults operator fee to zero when call fails' , async ( ) => {
264+ const gasUsed = '0x1' ;
265+ request = {
266+ ...request ,
267+ transactionMeta : {
268+ ...request . transactionMeta ,
269+ gasUsed,
270+ } ,
271+ } ;
272+
273+ contractGetOperatorFeeMock . mockRejectedValueOnce ( new Error ( 'revert' ) ) ;
274+
275+ const flow = new MockOracleLayer1GasFeeFlow ( false ) ;
276+ const response = await flow . getLayer1Fee ( request ) ;
277+
278+ expect ( contractGetOperatorFeeMock ) . toHaveBeenCalledTimes ( 1 ) ;
279+ expect ( response ) . toStrictEqual ( {
280+ layer1Fee : LAYER_1_FEE_MOCK ,
281+ } ) ;
282+ } ) ;
283+
284+ it ( 'defaults operator fee to zero when call returns undefined' , async ( ) => {
285+ const gasUsed = '0x2' ;
286+ request = {
287+ ...request ,
288+ transactionMeta : {
289+ ...request . transactionMeta ,
290+ gasUsed,
291+ } ,
292+ } ;
293+
294+ contractGetOperatorFeeMock . mockResolvedValueOnce (
295+ undefined as unknown as BigNumber ,
296+ ) ;
297+
298+ const flow = new MockOracleLayer1GasFeeFlow ( false ) ;
299+ const response = await flow . getLayer1Fee ( request ) ;
300+
301+ expect ( contractGetOperatorFeeMock ) . toHaveBeenCalledTimes ( 1 ) ;
302+ expect ( response ) . toStrictEqual ( {
303+ layer1Fee : LAYER_1_FEE_MOCK ,
304+ } ) ;
305+ } ) ;
231306 } ) ;
232307} ) ;
0 commit comments