@@ -22,6 +22,7 @@ import {
2222 AlreadyValidDASKeyset,
2323 NoSuchKeyset,
2424 NotForked,
25+ RollupNotChanged,
2526 DataBlobsNotSupported,
2627 InitParamZero,
2728 MissingDataHashes,
@@ -30,6 +31,7 @@ import {
3031 RollupNotChanged,
3132 EmptyBatchData,
3233 InvalidHeaderFlag,
34+ NativeTokenMismatch,
3335 Deprecated
3436} from "../libraries/Error.sol " ;
3537import "./IBridge.sol " ;
@@ -46,6 +48,7 @@ import "../libraries/DelegateCallAware.sol";
4648import {IGasRefunder} from "../libraries/IGasRefunder.sol " ;
4749import {GasRefundEnabled} from "../libraries/GasRefundEnabled.sol " ;
4850import "../libraries/ArbitrumChecker.sol " ;
51+ import {IERC20Bridge } from "./IERC20Bridge.sol " ;
4952
5053/**
5154 * @title Accepts batches from the sequencer and adds them to the rollup inbox.
@@ -110,15 +113,22 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
110113 uint256 internal immutable deployTimeChainId = block .chainid ;
111114 // If the chain this SequencerInbox is deployed on is an Arbitrum chain.
112115 bool internal immutable hostChainIsArbitrum = ArbitrumChecker.runningOnArbitrum ();
113-
114- constructor (uint256 _maxDataSize , IReader4844 reader4844_ ) {
116+ // True if the chain this SequencerInbox is deployed on uses custom fee token
117+ bool public immutable isUsingFeeToken;
118+
119+ constructor (
120+ uint256 _maxDataSize ,
121+ IReader4844 reader4844_ ,
122+ bool _isUsingFeeToken
123+ ) {
115124 maxDataSize = _maxDataSize;
116125 if (hostChainIsArbitrum) {
117126 if (reader4844_ != IReader4844 (address (0 ))) revert DataBlobsNotSupported ();
118127 } else {
119128 if (reader4844_ == IReader4844 (address (0 ))) revert InitParamZero ("Reader4844 " );
120129 }
121130 reader4844 = reader4844_;
131+ isUsingFeeToken = _isUsingFeeToken;
122132 }
123133
124134 function _chainIdChanged () internal view returns (bool ) {
@@ -163,6 +173,19 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
163173 ) external onlyDelegated {
164174 if (bridge != IBridge (address (0 ))) revert AlreadyInit ();
165175 if (bridge_ == IBridge (address (0 ))) revert HadZeroInit ();
176+
177+ // Make sure logic contract was created by proper value for 'isUsingFeeToken'.
178+ // Bridge in ETH based chains doesn't implement nativeToken(). In future it might implement it and return address(0)
179+ bool actualIsUsingFeeToken = false ;
180+ try IERC20Bridge (address (bridge_)).nativeToken () returns (address feeToken ) {
181+ if (feeToken != address (0 )) {
182+ actualIsUsingFeeToken = true ;
183+ }
184+ } catch {}
185+ if (isUsingFeeToken != actualIsUsingFeeToken) {
186+ revert NativeTokenMismatch ();
187+ }
188+
166189 bridge = bridge_;
167190 rollup = bridge_.rollup ();
168191 delayBlocks = maxTimeVariation_.delayBlocks;
@@ -432,7 +455,7 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
432455 // same as using calldata, we only submit spending report if the caller is the origin of the tx
433456 // such that one cannot "double-claim" batch posting refund in the same tx
434457 // solhint-disable-next-line avoid-tx-origin
435- if (msg .sender == tx .origin ) {
458+ if (msg .sender == tx .origin && ! isUsingFeeToken ) {
436459 submitBatchSpendingReport (dataHash, seqMessageIndex, block .basefee , blobGas);
437460 }
438461 }
@@ -670,7 +693,8 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
670693
671694 totalDelayedMessagesRead = afterDelayedMessagesRead;
672695
673- if (calldataLengthPosted > 0 ) {
696+ if (calldataLengthPosted > 0 && ! isUsingFeeToken) {
697+ // only report batch poster spendings if chain is using ETH as native currency
674698 submitBatchSpendingReport (dataHash, seqMessageIndex, block .basefee , 0 );
675699 }
676700 }
0 commit comments