Skip to content

Commit b4c739f

Browse files
authored
Merge pull request #108 from OffchainLabs/fee-token-reports
Do not send batch poster reports in fee token based chains
2 parents 7c841ee + 80d5415 commit b4c739f

File tree

10 files changed

+325
-53
lines changed

10 files changed

+325
-53
lines changed

deploy/SequencerInboxStubCreator.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,14 @@ module.exports = async hre => {
1717
}
1818
await deploy('SequencerInboxStub', {
1919
from: deployer,
20-
args: [bridge.address, deployer, maxTime, 117964, reader4844.address],
20+
args: [
21+
bridge.address,
22+
deployer,
23+
maxTime,
24+
117964,
25+
reader4844.address,
26+
false,
27+
],
2128
})
2229
}
2330

scripts/deployment.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ async function deployAllContracts(
8181
const ethBridge = await deployContract('Bridge', signer, [])
8282
const ethSequencerInbox = await deployContract('SequencerInbox', signer, [
8383
maxDataSize,
84+
false,
8485
])
8586
const ethInbox = await deployContract('Inbox', signer, [maxDataSize])
8687
const ethRollupEventInbox = await deployContract(
@@ -91,7 +92,10 @@ async function deployAllContracts(
9192
const ethOutbox = await deployContract('Outbox', signer, [])
9293

9394
const erc20Bridge = await deployContract('ERC20Bridge', signer, [])
94-
const erc20SequencerInbox = ethSequencerInbox
95+
const erc20SequencerInbox = await deployContract('SequencerInbox', signer, [
96+
maxDataSize,
97+
true,
98+
])
9599
const erc20Inbox = await deployContract('ERC20Inbox', signer, [maxDataSize])
96100
const erc20RollupEventInbox = await deployContract(
97101
'ERC20RollupEventInbox',

src/bridge/SequencerInbox.sol

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -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";
3537
import "./IBridge.sol";
@@ -46,6 +48,7 @@ import "../libraries/DelegateCallAware.sol";
4648
import {IGasRefunder} from "../libraries/IGasRefunder.sol";
4749
import {GasRefundEnabled} from "../libraries/GasRefundEnabled.sol";
4850
import "../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
}

src/libraries/Error.sol

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,5 +197,8 @@ error EmptyBatchData();
197197
/// @dev Unsupported header flag was provided
198198
error InvalidHeaderFlag(bytes1);
199199

200+
/// @dev SequencerInbox and Bridge are not in the same feeToken/ETH mode
201+
error NativeTokenMismatch();
202+
200203
/// @dev Thrown when a deprecated function is called
201204
error Deprecated();

src/mocks/SequencerInboxStub.sol

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ contract SequencerInboxStub is SequencerInbox {
1414
address sequencer_,
1515
ISequencerInbox.MaxTimeVariation memory maxTimeVariation_,
1616
uint256 maxDataSize_,
17-
IReader4844 reader4844_
18-
) SequencerInbox(maxDataSize_, reader4844_) {
17+
IReader4844 reader4844_,
18+
bool isUsingFeeToken_
19+
) SequencerInbox(maxDataSize_, reader4844_, isUsingFeeToken_) {
1920
bridge = bridge_;
2021
rollup = IOwnable(msg.sender);
2122
delayBlocks = maxTimeVariation_.delayBlocks;

test/contract/arbRollup.spec.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,8 @@ const setup = async () => {
191191
)) as SequencerInbox__factory
192192
const ethSequencerInbox = await ethSequencerInboxFac.deploy(
193193
117964,
194-
dummy4844Reader
194+
dummy4844Reader,
195+
false
195196
)
196197

197198
const ethInboxFac = (await ethers.getContractFactory(
@@ -214,7 +215,14 @@ const setup = async () => {
214215
)) as ERC20Bridge__factory
215216
const erc20Bridge = await erc20BridgeFac.deploy()
216217

217-
const erc20SequencerInbox = ethSequencerInbox
218+
const erc20SequencerInboxFac = (await ethers.getContractFactory(
219+
'SequencerInbox'
220+
)) as SequencerInbox__factory
221+
const erc20SequencerInbox = await erc20SequencerInboxFac.deploy(
222+
117964,
223+
dummy4844Reader,
224+
true
225+
)
218226

219227
const erc20InboxFac = (await ethers.getContractFactory(
220228
'ERC20Inbox'

test/contract/sequencerInboxForceInclude.spec.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,8 @@ describe('SequencerInboxForceInclude', async () => {
237237
)) as SequencerInbox__factory
238238
const seqInboxTemplate = await sequencerInboxFac.deploy(
239239
117964,
240-
reader4844.address
240+
reader4844.address,
241+
false
241242
)
242243
const inboxFac = (await ethers.getContractFactory(
243244
'Inbox'

test/foundry/BridgeCreator.t.sol

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ contract BridgeCreatorTest is Test {
2020
bridge: new Bridge(),
2121
sequencerInbox: new SequencerInbox(
2222
MAX_DATA_SIZE,
23-
dummyReader4844
23+
dummyReader4844,
24+
false
2425
),
2526
inbox: new Inbox(MAX_DATA_SIZE),
2627
rollupEventInbox: new RollupEventInbox(),
@@ -29,7 +30,11 @@ contract BridgeCreatorTest is Test {
2930
BridgeCreator.BridgeContracts erc20BasedTemplates =
3031
BridgeCreator.BridgeContracts({
3132
bridge: new ERC20Bridge(),
32-
sequencerInbox: ethBasedTemplates.sequencerInbox,
33+
sequencerInbox: new SequencerInbox(
34+
MAX_DATA_SIZE,
35+
dummyReader4844,
36+
true
37+
),
3338
inbox: new ERC20Inbox(MAX_DATA_SIZE),
3439
rollupEventInbox: new ERC20RollupEventInbox(),
3540
outbox: new ERC20Outbox()
@@ -40,7 +45,7 @@ contract BridgeCreatorTest is Test {
4045
creator = new BridgeCreator(ethBasedTemplates, erc20BasedTemplates);
4146
}
4247

43-
function getEthBasedTemplates() internal returns (BridgeCreator.BridgeContracts memory) {
48+
function getEthBasedTemplates() internal view returns (BridgeCreator.BridgeContracts memory) {
4449
BridgeCreator.BridgeContracts memory templates;
4550
(
4651
templates.bridge,
@@ -52,7 +57,7 @@ contract BridgeCreatorTest is Test {
5257
return templates;
5358
}
5459

55-
function getErc20BasedTemplates() internal returns (BridgeCreator.BridgeContracts memory) {
60+
function getErc20BasedTemplates() internal view returns (BridgeCreator.BridgeContracts memory) {
5661
BridgeCreator.BridgeContracts memory templates;
5762
(
5863
templates.bridge,

test/foundry/RollupCreator.t.sol

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,20 @@ contract RollupCreatorTest is Test {
3737
bridge: new Bridge(),
3838
sequencerInbox: new SequencerInbox(
3939
MAX_DATA_SIZE,
40-
dummyReader4844
40+
dummyReader4844,
41+
false
4142
),
4243
inbox: new Inbox(MAX_DATA_SIZE),
4344
rollupEventInbox: new RollupEventInbox(),
4445
outbox: new Outbox()
4546
});
4647
BridgeCreator.BridgeContracts public erc20BasedTemplates = BridgeCreator.BridgeContracts({
4748
bridge: new ERC20Bridge(),
48-
sequencerInbox: ethBasedTemplates.sequencerInbox,
49+
sequencerInbox: new SequencerInbox(
50+
MAX_DATA_SIZE,
51+
dummyReader4844,
52+
true
53+
),
4954
inbox: new ERC20Inbox(MAX_DATA_SIZE),
5055
rollupEventInbox: new ERC20RollupEventInbox(),
5156
outbox: new ERC20Outbox()

0 commit comments

Comments
 (0)