@arbitrum/nitro-contracts 1.0.0-beta.8 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- package/package.json +10 -2
- package/src/bridge/Bridge.sol +39 -30
- package/src/bridge/IBridge.sol +56 -29
- package/src/bridge/IInbox.sol +130 -15
- package/src/bridge/IOutbox.sol +55 -7
- package/src/bridge/ISequencerInbox.sol +84 -7
- package/src/bridge/Inbox.sol +154 -92
- package/src/bridge/Outbox.sol +23 -47
- package/src/bridge/SequencerInbox.sol +132 -62
- package/src/challenge/ChallengeManager.sol +0 -9
- package/src/challenge/IChallengeManager.sol +0 -2
- package/src/libraries/AdminFallbackProxy.sol +4 -4
- package/src/libraries/Constants.sol +3 -0
- package/src/libraries/{SecondaryLogicUUPSUpgradeable.sol → DoubleLogicUUPSUpgradeable.sol} +2 -1
- package/src/libraries/Error.sol +12 -0
- package/src/libraries/IGasRefunder.sol +11 -5
- package/src/libraries/MerkleLib.sol +5 -3
- package/src/mocks/BridgeStub.sol +20 -1
- package/src/mocks/BridgeUnproxied.sol +17 -0
- package/src/mocks/InboxStub.sol +48 -3
- package/src/mocks/SequencerInboxStub.sol +13 -3
- package/src/mocks/Simple.sol +69 -0
- package/src/node-interface/NodeInterface.sol +35 -4
- package/src/precompiles/ArbGasInfo.sol +7 -4
- package/src/precompiles/ArbOwner.sol +9 -0
- package/src/precompiles/ArbOwnerPublic.sol +3 -0
- package/src/precompiles/ArbSys.sol +5 -2
- package/src/rollup/IRollupCore.sol +2 -0
- package/src/rollup/IRollupLogic.sol +10 -0
- package/src/rollup/RollupAdminLogic.sol +27 -3
- package/src/rollup/RollupCore.sol +3 -0
- package/src/rollup/RollupCreator.sol +3 -3
- package/src/rollup/RollupEventInbox.sol +3 -6
- package/src/{libraries/ArbitrumProxy.sol → rollup/RollupProxy.sol} +3 -3
- package/src/rollup/RollupUserLogic.sol +47 -10
- package/src/test-helpers/BridgeTester.sol +7 -1
- package/src/test-helpers/OutboxWithoutOptTester.sol +8 -8
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@arbitrum/nitro-contracts",
|
3
|
-
"version": "1.0.0
|
3
|
+
"version": "1.0.0",
|
4
4
|
"description": "Layer 2 precompiles and rollup for Arbitrum Nitro",
|
5
5
|
"author": "Offchain Labs, Inc.",
|
6
6
|
"license": "BUSL-1.1",
|
@@ -24,7 +24,9 @@
|
|
24
24
|
"hardhat:prod": "hardhat --config hardhat.prod-config.js",
|
25
25
|
"build:0.6": "INTERFACE_TESTER_SOLC_VERSION=0.6.9 yarn run build",
|
26
26
|
"build:0.7": "INTERFACE_TESTER_SOLC_VERSION=0.7.0 yarn run build",
|
27
|
-
"test:compatibility": "yarn run build:0.6 && yarn run build:0.7"
|
27
|
+
"test:compatibility": "yarn run build:0.6 && yarn run build:0.7",
|
28
|
+
"test:storage": "./test/storage/test.bash",
|
29
|
+
"postinstall": "patch-package"
|
28
30
|
},
|
29
31
|
"dependencies": {
|
30
32
|
"@openzeppelin/contracts": "4.5.0",
|
@@ -34,6 +36,7 @@
|
|
34
36
|
"private": false,
|
35
37
|
"devDependencies": {
|
36
38
|
"@nomiclabs/hardhat-ethers": "npm:hardhat-deploy-ethers@^0.3.0-beta.13",
|
39
|
+
"@nomiclabs/hardhat-etherscan": "^3.1.0",
|
37
40
|
"@nomiclabs/hardhat-waffle": "^2.0.1",
|
38
41
|
"@typechain/ethers-v5": "^10.0.0",
|
39
42
|
"@typechain/hardhat": "^6.0.0",
|
@@ -45,6 +48,8 @@
|
|
45
48
|
"ethers": "^5.5.2",
|
46
49
|
"hardhat-deploy": "^0.11.4",
|
47
50
|
"hardhat-gas-reporter": "^1.0.8",
|
51
|
+
"patch-package": "^6.4.7",
|
52
|
+
"postinstall-postinstall": "^2.1.0",
|
48
53
|
"prettier": "^2.5.1",
|
49
54
|
"prettier-plugin-solidity": "^1.0.0-beta.19",
|
50
55
|
"solhint": "^3.3.7",
|
@@ -53,5 +58,8 @@
|
|
53
58
|
"ts-node": "^10.4.0",
|
54
59
|
"typechain": "^8.0.0",
|
55
60
|
"typescript": "^4.5.4"
|
61
|
+
},
|
62
|
+
"optionalDependencies":{
|
63
|
+
"sol2uml": "2.2.0"
|
56
64
|
}
|
57
65
|
}
|
package/src/bridge/Bridge.sol
CHANGED
@@ -13,7 +13,8 @@ import {
|
|
13
13
|
NotDelayedInbox,
|
14
14
|
NotSequencerInbox,
|
15
15
|
NotOutbox,
|
16
|
-
InvalidOutboxSet
|
16
|
+
InvalidOutboxSet,
|
17
|
+
BadSequencerMessageNumber
|
17
18
|
} from "../libraries/Error.sol";
|
18
19
|
import "./IBridge.sol";
|
19
20
|
import "./Messages.sol";
|
@@ -42,18 +43,20 @@ contract Bridge is Initializable, DelegateCallAware, IBridge {
|
|
42
43
|
address[] public allowedDelayedInboxList;
|
43
44
|
address[] public allowedOutboxList;
|
44
45
|
|
45
|
-
address
|
46
|
+
address internal _activeOutbox;
|
46
47
|
|
47
|
-
/// @
|
48
|
-
bytes32[] public
|
48
|
+
/// @inheritdoc IBridge
|
49
|
+
bytes32[] public delayedInboxAccs;
|
49
50
|
|
50
|
-
/// @
|
51
|
-
bytes32[] public
|
51
|
+
/// @inheritdoc IBridge
|
52
|
+
bytes32[] public sequencerInboxAccs;
|
52
53
|
|
53
|
-
IOwnable public
|
54
|
+
IOwnable public rollup;
|
54
55
|
address public sequencerInbox;
|
55
56
|
|
56
|
-
|
57
|
+
uint256 public override sequencerReportedSubMessageCount;
|
58
|
+
|
59
|
+
address internal constant EMPTY_ACTIVEOUTBOX = address(type(uint160).max);
|
57
60
|
|
58
61
|
function initialize(IOwnable rollup_) external initializer onlyDelegated {
|
59
62
|
_activeOutbox = EMPTY_ACTIVEOUTBOX;
|
@@ -81,11 +84,11 @@ contract Bridge is Initializable, DelegateCallAware, IBridge {
|
|
81
84
|
return outbox;
|
82
85
|
}
|
83
86
|
|
84
|
-
function allowedDelayedInboxes(address inbox) external view
|
87
|
+
function allowedDelayedInboxes(address inbox) external view returns (bool) {
|
85
88
|
return allowedDelayedInboxesMap[inbox].allowed;
|
86
89
|
}
|
87
90
|
|
88
|
-
function allowedOutboxes(address outbox) external view
|
91
|
+
function allowedOutboxes(address outbox) external view returns (bool) {
|
89
92
|
return allowedOutboxesMap[outbox].allowed;
|
90
93
|
}
|
91
94
|
|
@@ -94,9 +97,13 @@ contract Bridge is Initializable, DelegateCallAware, IBridge {
|
|
94
97
|
_;
|
95
98
|
}
|
96
99
|
|
97
|
-
function enqueueSequencerMessage(
|
100
|
+
function enqueueSequencerMessage(
|
101
|
+
bytes32 dataHash,
|
102
|
+
uint256 afterDelayedMessagesRead,
|
103
|
+
uint256 prevMessageCount,
|
104
|
+
uint256 newMessageCount
|
105
|
+
)
|
98
106
|
external
|
99
|
-
override
|
100
107
|
onlySequencerInbox
|
101
108
|
returns (
|
102
109
|
uint256 seqMessageIndex,
|
@@ -105,6 +112,14 @@ contract Bridge is Initializable, DelegateCallAware, IBridge {
|
|
105
112
|
bytes32 acc
|
106
113
|
)
|
107
114
|
{
|
115
|
+
if (
|
116
|
+
sequencerReportedSubMessageCount != prevMessageCount &&
|
117
|
+
prevMessageCount != 0 &&
|
118
|
+
sequencerReportedSubMessageCount != 0
|
119
|
+
) {
|
120
|
+
revert BadSequencerMessageNumber(sequencerReportedSubMessageCount, prevMessageCount);
|
121
|
+
}
|
122
|
+
sequencerReportedSubMessageCount = newMessageCount;
|
108
123
|
seqMessageIndex = sequencerInboxAccs.length;
|
109
124
|
if (sequencerInboxAccs.length > 0) {
|
110
125
|
beforeAcc = sequencerInboxAccs[sequencerInboxAccs.length - 1];
|
@@ -116,15 +131,9 @@ contract Bridge is Initializable, DelegateCallAware, IBridge {
|
|
116
131
|
sequencerInboxAccs.push(acc);
|
117
132
|
}
|
118
133
|
|
119
|
-
|
120
|
-
* @dev allows the sequencer inbox to submit a delayed message of the batchPostingReport type
|
121
|
-
* This is done through a separate function entrypoint instead of allowing the sequencer inbox
|
122
|
-
* to call `enqueueDelayedMessage` to avoid the gas overhead of an extra SLOAD in either
|
123
|
-
* every delayed inbox or every sequencer inbox call.
|
124
|
-
*/
|
134
|
+
/// @inheritdoc IBridge
|
125
135
|
function submitBatchSpendingReport(address sender, bytes32 messageDataHash)
|
126
136
|
external
|
127
|
-
override
|
128
137
|
onlySequencerInbox
|
129
138
|
returns (uint256)
|
130
139
|
{
|
@@ -139,16 +148,12 @@ contract Bridge is Initializable, DelegateCallAware, IBridge {
|
|
139
148
|
);
|
140
149
|
}
|
141
150
|
|
142
|
-
|
143
|
-
* @dev Enqueue a message in the delayed inbox accumulator.
|
144
|
-
* These messages are later sequenced in the SequencerInbox, either by the sequencer as
|
145
|
-
* part of a normal batch, or by force inclusion.
|
146
|
-
*/
|
151
|
+
/// @inheritdoc IBridge
|
147
152
|
function enqueueDelayedMessage(
|
148
153
|
uint8 kind,
|
149
154
|
address sender,
|
150
155
|
bytes32 messageDataHash
|
151
|
-
) external payable
|
156
|
+
) external payable returns (uint256) {
|
152
157
|
if (!allowedDelayedInboxesMap[msg.sender].allowed) revert NotDelayedInbox(msg.sender);
|
153
158
|
return
|
154
159
|
addMessageToDelayedAccumulator(
|
@@ -201,7 +206,7 @@ contract Bridge is Initializable, DelegateCallAware, IBridge {
|
|
201
206
|
address to,
|
202
207
|
uint256 value,
|
203
208
|
bytes calldata data
|
204
|
-
) external
|
209
|
+
) external returns (bool success, bytes memory returnData) {
|
205
210
|
if (!allowedOutboxesMap[msg.sender].allowed) revert NotOutbox(msg.sender);
|
206
211
|
if (data.length > 0 && !to.isContract()) revert NotContract(to);
|
207
212
|
address prevOutbox = _activeOutbox;
|
@@ -216,12 +221,12 @@ contract Bridge is Initializable, DelegateCallAware, IBridge {
|
|
216
221
|
emit BridgeCallTriggered(msg.sender, to, value, data);
|
217
222
|
}
|
218
223
|
|
219
|
-
function setSequencerInbox(address _sequencerInbox) external
|
224
|
+
function setSequencerInbox(address _sequencerInbox) external onlyRollupOrOwner {
|
220
225
|
sequencerInbox = _sequencerInbox;
|
221
226
|
emit SequencerInboxUpdated(_sequencerInbox);
|
222
227
|
}
|
223
228
|
|
224
|
-
function setDelayedInbox(address inbox, bool enabled) external
|
229
|
+
function setDelayedInbox(address inbox, bool enabled) external onlyRollupOrOwner {
|
225
230
|
InOutInfo storage info = allowedDelayedInboxesMap[inbox];
|
226
231
|
bool alreadyEnabled = info.allowed;
|
227
232
|
emit InboxToggle(inbox, enabled);
|
@@ -241,7 +246,7 @@ contract Bridge is Initializable, DelegateCallAware, IBridge {
|
|
241
246
|
}
|
242
247
|
}
|
243
248
|
|
244
|
-
function setOutbox(address outbox, bool enabled) external
|
249
|
+
function setOutbox(address outbox, bool enabled) external onlyRollupOrOwner {
|
245
250
|
if (outbox == EMPTY_ACTIVEOUTBOX) revert InvalidOutboxSet(outbox);
|
246
251
|
|
247
252
|
InOutInfo storage info = allowedOutboxesMap[outbox];
|
@@ -261,11 +266,15 @@ contract Bridge is Initializable, DelegateCallAware, IBridge {
|
|
261
266
|
}
|
262
267
|
}
|
263
268
|
|
269
|
+
function setSequencerReportedSubMessageCount(uint256 newMsgCount) external onlyRollupOrOwner {
|
270
|
+
sequencerReportedSubMessageCount = newMsgCount;
|
271
|
+
}
|
272
|
+
|
264
273
|
function delayedMessageCount() external view override returns (uint256) {
|
265
274
|
return delayedInboxAccs.length;
|
266
275
|
}
|
267
276
|
|
268
|
-
function sequencerMessageCount() external view
|
277
|
+
function sequencerMessageCount() external view returns (uint256) {
|
269
278
|
return sequencerInboxAccs.length;
|
270
279
|
}
|
271
280
|
|
package/src/bridge/IBridge.sol
CHANGED
@@ -32,13 +32,57 @@ interface IBridge {
|
|
32
32
|
|
33
33
|
event SequencerInboxUpdated(address newSequencerInbox);
|
34
34
|
|
35
|
+
function allowedDelayedInboxList(uint256) external returns (address);
|
36
|
+
|
37
|
+
function allowedOutboxList(uint256) external returns (address);
|
38
|
+
|
39
|
+
/// @dev Accumulator for delayed inbox messages; tail represents hash of the current state; each element represents the inclusion of a new message.
|
40
|
+
function delayedInboxAccs(uint256) external view returns (bytes32);
|
41
|
+
|
42
|
+
/// @dev Accumulator for sequencer inbox messages; tail represents hash of the current state; each element represents the inclusion of a new message.
|
43
|
+
function sequencerInboxAccs(uint256) external view returns (bytes32);
|
44
|
+
|
45
|
+
function rollup() external view returns (IOwnable);
|
46
|
+
|
47
|
+
function sequencerInbox() external view returns (address);
|
48
|
+
|
49
|
+
function activeOutbox() external view returns (address);
|
50
|
+
|
51
|
+
function allowedDelayedInboxes(address inbox) external view returns (bool);
|
52
|
+
|
53
|
+
function allowedOutboxes(address outbox) external view returns (bool);
|
54
|
+
|
55
|
+
function sequencerReportedSubMessageCount() external view returns (uint256);
|
56
|
+
|
57
|
+
/**
|
58
|
+
* @dev Enqueue a message in the delayed inbox accumulator.
|
59
|
+
* These messages are later sequenced in the SequencerInbox, either
|
60
|
+
* by the sequencer as part of a normal batch, or by force inclusion.
|
61
|
+
*/
|
35
62
|
function enqueueDelayedMessage(
|
36
63
|
uint8 kind,
|
37
64
|
address sender,
|
38
65
|
bytes32 messageDataHash
|
39
66
|
) external payable returns (uint256);
|
40
67
|
|
41
|
-
function
|
68
|
+
function executeCall(
|
69
|
+
address to,
|
70
|
+
uint256 value,
|
71
|
+
bytes calldata data
|
72
|
+
) external returns (bool success, bytes memory returnData);
|
73
|
+
|
74
|
+
function delayedMessageCount() external view returns (uint256);
|
75
|
+
|
76
|
+
function sequencerMessageCount() external view returns (uint256);
|
77
|
+
|
78
|
+
// ---------- onlySequencerInbox functions ----------
|
79
|
+
|
80
|
+
function enqueueSequencerMessage(
|
81
|
+
bytes32 dataHash,
|
82
|
+
uint256 afterDelayedMessagesRead,
|
83
|
+
uint256 prevMessageCount,
|
84
|
+
uint256 newMessageCount
|
85
|
+
)
|
42
86
|
external
|
43
87
|
returns (
|
44
88
|
uint256 seqMessageIndex,
|
@@ -47,42 +91,25 @@ interface IBridge {
|
|
47
91
|
bytes32 acc
|
48
92
|
);
|
49
93
|
|
94
|
+
/**
|
95
|
+
* @dev Allows the sequencer inbox to submit a delayed message of the batchPostingReport type
|
96
|
+
* This is done through a separate function entrypoint instead of allowing the sequencer inbox
|
97
|
+
* to call `enqueueDelayedMessage` to avoid the gas overhead of an extra SLOAD in either
|
98
|
+
* every delayed inbox or every sequencer inbox call.
|
99
|
+
*/
|
50
100
|
function submitBatchSpendingReport(address batchPoster, bytes32 dataHash)
|
51
101
|
external
|
52
102
|
returns (uint256 msgNum);
|
53
103
|
|
54
|
-
|
55
|
-
address to,
|
56
|
-
uint256 value,
|
57
|
-
bytes calldata data
|
58
|
-
) external returns (bool success, bytes memory returnData);
|
59
|
-
|
60
|
-
// These are only callable by the admin
|
61
|
-
function setDelayedInbox(address inbox, bool enabled) external;
|
62
|
-
|
63
|
-
function setOutbox(address inbox, bool enabled) external;
|
104
|
+
// ---------- onlyRollupOrOwner functions ----------
|
64
105
|
|
65
106
|
function setSequencerInbox(address _sequencerInbox) external;
|
66
107
|
|
67
|
-
|
68
|
-
|
69
|
-
function sequencerInbox() external view returns (address);
|
70
|
-
|
71
|
-
function activeOutbox() external view returns (address);
|
72
|
-
|
73
|
-
function allowedDelayedInboxes(address inbox) external view returns (bool);
|
74
|
-
|
75
|
-
function allowedOutboxes(address outbox) external view returns (bool);
|
76
|
-
|
77
|
-
function delayedInboxAccs(uint256 index) external view returns (bytes32);
|
78
|
-
|
79
|
-
function sequencerInboxAccs(uint256 index) external view returns (bytes32);
|
80
|
-
|
81
|
-
function delayedMessageCount() external view returns (uint256);
|
108
|
+
function setDelayedInbox(address inbox, bool enabled) external;
|
82
109
|
|
83
|
-
function
|
110
|
+
function setOutbox(address inbox, bool enabled) external;
|
84
111
|
|
85
|
-
|
112
|
+
// ---------- initializer ----------
|
86
113
|
|
87
|
-
function
|
114
|
+
function initialize(IOwnable rollup_) external;
|
88
115
|
}
|
package/src/bridge/IInbox.sol
CHANGED
@@ -7,10 +7,44 @@ pragma solidity >=0.6.9 <0.9.0;
|
|
7
7
|
|
8
8
|
import "./IBridge.sol";
|
9
9
|
import "./IDelayedMessageProvider.sol";
|
10
|
+
import "./ISequencerInbox.sol";
|
10
11
|
|
11
12
|
interface IInbox is IDelayedMessageProvider {
|
13
|
+
function bridge() external view returns (IBridge);
|
14
|
+
|
15
|
+
function sequencerInbox() external view returns (ISequencerInbox);
|
16
|
+
|
17
|
+
/**
|
18
|
+
* @notice Send a generic L2 message to the chain
|
19
|
+
* @dev This method is an optimization to avoid having to emit the entirety of the messageData in a log. Instead validators are expected to be able to parse the data from the transaction's input
|
20
|
+
* This method will be disabled upon L1 fork to prevent replay attacks on L2
|
21
|
+
* @param messageData Data of the message being sent
|
22
|
+
*/
|
23
|
+
function sendL2MessageFromOrigin(bytes calldata messageData) external returns (uint256);
|
24
|
+
|
25
|
+
/**
|
26
|
+
* @notice Send a generic L2 message to the chain
|
27
|
+
* @dev This method can be used to send any type of message that doesn't require L1 validation
|
28
|
+
* This method will be disabled upon L1 fork to prevent replay attacks on L2
|
29
|
+
* @param messageData Data of the message being sent
|
30
|
+
*/
|
12
31
|
function sendL2Message(bytes calldata messageData) external returns (uint256);
|
13
32
|
|
33
|
+
function sendL1FundedUnsignedTransaction(
|
34
|
+
uint256 gasLimit,
|
35
|
+
uint256 maxFeePerGas,
|
36
|
+
uint256 nonce,
|
37
|
+
address to,
|
38
|
+
bytes calldata data
|
39
|
+
) external payable returns (uint256);
|
40
|
+
|
41
|
+
function sendL1FundedContractTransaction(
|
42
|
+
uint256 gasLimit,
|
43
|
+
uint256 maxFeePerGas,
|
44
|
+
address to,
|
45
|
+
bytes calldata data
|
46
|
+
) external payable returns (uint256);
|
47
|
+
|
14
48
|
function sendUnsignedTransaction(
|
15
49
|
uint256 gasLimit,
|
16
50
|
uint256 maxFeePerGas,
|
@@ -28,7 +62,11 @@ interface IInbox is IDelayedMessageProvider {
|
|
28
62
|
bytes calldata data
|
29
63
|
) external returns (uint256);
|
30
64
|
|
31
|
-
|
65
|
+
/**
|
66
|
+
* @dev This method can only be called upon L1 fork and will not alias the caller
|
67
|
+
* This method will revert if not called from origin
|
68
|
+
*/
|
69
|
+
function sendL1FundedUnsignedTransactionToFork(
|
32
70
|
uint256 gasLimit,
|
33
71
|
uint256 maxFeePerGas,
|
34
72
|
uint256 nonce,
|
@@ -36,43 +74,120 @@ interface IInbox is IDelayedMessageProvider {
|
|
36
74
|
bytes calldata data
|
37
75
|
) external payable returns (uint256);
|
38
76
|
|
39
|
-
|
77
|
+
/**
|
78
|
+
* @dev This method can only be called upon L1 fork and will not alias the caller
|
79
|
+
* This method will revert if not called from origin
|
80
|
+
*/
|
81
|
+
function sendUnsignedTransactionToFork(
|
40
82
|
uint256 gasLimit,
|
41
83
|
uint256 maxFeePerGas,
|
84
|
+
uint256 nonce,
|
42
85
|
address to,
|
86
|
+
uint256 value,
|
43
87
|
bytes calldata data
|
44
|
-
) external
|
88
|
+
) external returns (uint256);
|
45
89
|
|
46
|
-
|
90
|
+
/**
|
91
|
+
* @notice Send a message to initiate L2 withdrawal
|
92
|
+
* @dev This method can only be called upon L1 fork and will not alias the caller
|
93
|
+
* This method will revert if not called from origin
|
94
|
+
*/
|
95
|
+
function sendWithdrawEthToFork(
|
96
|
+
uint256 gasLimit,
|
97
|
+
uint256 maxFeePerGas,
|
98
|
+
uint256 nonce,
|
99
|
+
uint256 value,
|
100
|
+
address withdrawTo
|
101
|
+
) external returns (uint256);
|
102
|
+
|
103
|
+
/**
|
104
|
+
* @notice Get the L1 fee for submitting a retryable
|
105
|
+
* @dev This fee can be paid by funds already in the L2 aliased address or by the current message value
|
106
|
+
* @dev This formula may change in the future, to future proof your code query this method instead of inlining!!
|
107
|
+
* @param dataLength The length of the retryable's calldata, in bytes
|
108
|
+
* @param baseFee The block basefee when the retryable is included in the chain, if 0 current block.basefee will be used
|
109
|
+
*/
|
110
|
+
function calculateRetryableSubmissionFee(uint256 dataLength, uint256 baseFee)
|
111
|
+
external
|
112
|
+
view
|
113
|
+
returns (uint256);
|
114
|
+
|
115
|
+
/**
|
116
|
+
* @notice Deposit eth from L1 to L2 to address of the sender if sender is an EOA, and to its aliased address if the sender is a contract
|
117
|
+
* @dev This does not trigger the fallback function when receiving in the L2 side.
|
118
|
+
* Look into retryable tickets if you are interested in this functionality.
|
119
|
+
* @dev This function should not be called inside contract constructors
|
120
|
+
*/
|
121
|
+
function depositEth() external payable returns (uint256);
|
122
|
+
|
123
|
+
/**
|
124
|
+
* @notice Put a message in the L2 inbox that can be reexecuted for some fixed amount of time if it reverts
|
125
|
+
* @dev all msg.value will deposited to callValueRefundAddress on L2
|
126
|
+
* @dev Gas limit and maxFeePerGas should not be set to 1 as that is used to trigger the RetryableData error
|
127
|
+
* @param to destination L2 contract address
|
128
|
+
* @param l2CallValue call value for retryable L2 message
|
129
|
+
* @param maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee
|
130
|
+
* @param excessFeeRefundAddress gasLimit x maxFeePerGas - execution cost gets credited here on L2 balance
|
131
|
+
* @param callValueRefundAddress l2Callvalue gets credited here on L2 if retryable txn times out or gets cancelled
|
132
|
+
* @param gasLimit Max gas deducted from user's L2 balance to cover L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error)
|
133
|
+
* @param maxFeePerGas price bid for L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error)
|
134
|
+
* @param data ABI encoded data of L2 message
|
135
|
+
* @return unique message number of the retryable transaction
|
136
|
+
*/
|
47
137
|
function createRetryableTicket(
|
48
138
|
address to,
|
49
|
-
uint256
|
139
|
+
uint256 l2CallValue,
|
50
140
|
uint256 maxSubmissionCost,
|
51
|
-
address
|
52
|
-
address
|
141
|
+
address excessFeeRefundAddress,
|
142
|
+
address callValueRefundAddress,
|
53
143
|
uint256 gasLimit,
|
54
144
|
uint256 maxFeePerGas,
|
55
145
|
bytes calldata data
|
56
146
|
) external payable returns (uint256);
|
57
147
|
|
58
|
-
|
148
|
+
/**
|
149
|
+
* @notice Put a message in the L2 inbox that can be reexecuted for some fixed amount of time if it reverts
|
150
|
+
* @dev Same as createRetryableTicket, but does not guarantee that submission will succeed by requiring the needed funds
|
151
|
+
* come from the deposit alone, rather than falling back on the user's L2 balance
|
152
|
+
* @dev Advanced usage only (does not rewrite aliases for excessFeeRefundAddress and callValueRefundAddress).
|
153
|
+
* createRetryableTicket method is the recommended standard.
|
154
|
+
* @dev Gas limit and maxFeePerGas should not be set to 1 as that is used to trigger the RetryableData error
|
155
|
+
* @param to destination L2 contract address
|
156
|
+
* @param l2CallValue call value for retryable L2 message
|
157
|
+
* @param maxSubmissionCost Max gas deducted from user's L2 balance to cover base submission fee
|
158
|
+
* @param excessFeeRefundAddress gasLimit x maxFeePerGas - execution cost gets credited here on L2 balance
|
159
|
+
* @param callValueRefundAddress l2Callvalue gets credited here on L2 if retryable txn times out or gets cancelled
|
160
|
+
* @param gasLimit Max gas deducted from user's L2 balance to cover L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error)
|
161
|
+
* @param maxFeePerGas price bid for L2 execution. Should not be set to 1 (magic value used to trigger the RetryableData error)
|
162
|
+
* @param data ABI encoded data of L2 message
|
163
|
+
* @return unique message number of the retryable transaction
|
164
|
+
*/
|
59
165
|
function unsafeCreateRetryableTicket(
|
60
166
|
address to,
|
61
|
-
uint256
|
167
|
+
uint256 l2CallValue,
|
62
168
|
uint256 maxSubmissionCost,
|
63
|
-
address
|
64
|
-
address
|
169
|
+
address excessFeeRefundAddress,
|
170
|
+
address callValueRefundAddress,
|
65
171
|
uint256 gasLimit,
|
66
172
|
uint256 maxFeePerGas,
|
67
173
|
bytes calldata data
|
68
174
|
) external payable returns (uint256);
|
69
175
|
|
70
|
-
|
176
|
+
// ---------- onlyRollupOrOwner functions ----------
|
71
177
|
|
72
|
-
/// @notice
|
73
|
-
function
|
178
|
+
/// @notice pauses all inbox functionality
|
179
|
+
function pause() external;
|
74
180
|
|
75
|
-
|
181
|
+
/// @notice unpauses all inbox functionality
|
182
|
+
function unpause() external;
|
76
183
|
|
184
|
+
// ---------- initializer ----------
|
185
|
+
|
186
|
+
/**
|
187
|
+
* @dev function to be called one time during the inbox upgrade process
|
188
|
+
* this is used to fix the storage slots
|
189
|
+
*/
|
77
190
|
function postUpgradeInit(IBridge _bridge) external;
|
191
|
+
|
192
|
+
function initialize(IBridge _bridge, ISequencerInbox _sequencerInbox) external;
|
78
193
|
}
|
package/src/bridge/IOutbox.sol
CHANGED
@@ -5,8 +5,10 @@
|
|
5
5
|
// solhint-disable-next-line compiler-version
|
6
6
|
pragma solidity >=0.6.9 <0.9.0;
|
7
7
|
|
8
|
+
import "./IBridge.sol";
|
9
|
+
|
8
10
|
interface IOutbox {
|
9
|
-
event SendRootUpdated(bytes32 indexed
|
11
|
+
event SendRootUpdated(bytes32 indexed outputRoot, bytes32 indexed l2BlockHash);
|
10
12
|
event OutBoxTransactionExecuted(
|
11
13
|
address indexed to,
|
12
14
|
address indexed l2Sender,
|
@@ -14,21 +16,52 @@ interface IOutbox {
|
|
14
16
|
uint256 transactionIndex
|
15
17
|
);
|
16
18
|
|
19
|
+
function rollup() external view returns (address); // the rollup contract
|
20
|
+
|
21
|
+
function bridge() external view returns (IBridge); // the bridge contract
|
22
|
+
|
23
|
+
function spent(uint256) external view returns (bytes32); // packed spent bitmap
|
24
|
+
|
25
|
+
function roots(bytes32) external view returns (bytes32); // maps root hashes => L2 block hash
|
26
|
+
|
27
|
+
// solhint-disable-next-line func-name-mixedcase
|
28
|
+
function OUTBOX_VERSION() external view returns (uint128); // the outbox version
|
29
|
+
|
30
|
+
function updateSendRoot(bytes32 sendRoot, bytes32 l2BlockHash) external;
|
31
|
+
|
32
|
+
/// @notice When l2ToL1Sender returns a nonzero address, the message was originated by an L2 account
|
33
|
+
/// When the return value is zero, that means this is a system message
|
34
|
+
/// @dev the l2ToL1Sender behaves as the tx.origin, the msg.sender should be validated to protect against reentrancies
|
17
35
|
function l2ToL1Sender() external view returns (address);
|
18
36
|
|
37
|
+
/// @return l2Block return L2 block when the L2 tx was initiated or 0 if no L2 to L1 transaction is active
|
19
38
|
function l2ToL1Block() external view returns (uint256);
|
20
39
|
|
40
|
+
/// @return l1Block return L1 block when the L2 tx was initiated or 0 if no L2 to L1 transaction is active
|
21
41
|
function l2ToL1EthBlock() external view returns (uint256);
|
22
42
|
|
43
|
+
/// @return timestamp return L2 timestamp when the L2 tx was initiated or 0 if no L2 to L1 transaction is active
|
23
44
|
function l2ToL1Timestamp() external view returns (uint256);
|
24
45
|
|
25
|
-
|
26
|
-
function l2ToL1BatchNum() external view returns (uint256);
|
27
|
-
|
46
|
+
/// @return outputId returns the unique output identifier of the L2 to L1 tx or 0 if no L2 to L1 transaction is active
|
28
47
|
function l2ToL1OutputId() external view returns (bytes32);
|
29
48
|
|
30
|
-
|
31
|
-
|
49
|
+
/**
|
50
|
+
* @notice Executes a messages in an Outbox entry.
|
51
|
+
* @dev Reverts if dispute period hasn't expired, since the outbox entry
|
52
|
+
* is only created once the rollup confirms the respective assertion.
|
53
|
+
* @dev it is not possible to execute any L2-to-L1 transaction which contains data
|
54
|
+
* to a contract address without any code (as enforced by the Bridge contract).
|
55
|
+
* @param proof Merkle proof of message inclusion in send root
|
56
|
+
* @param index Merkle path to message
|
57
|
+
* @param l2Sender sender if original message (i.e., caller of ArbSys.sendTxToL1)
|
58
|
+
* @param to destination address for L1 contract call
|
59
|
+
* @param l2Block l2 block number at which sendTxToL1 call was made
|
60
|
+
* @param l1Block l1 block number at which sendTxToL1 call was made
|
61
|
+
* @param l2Timestamp l2 Timestamp at which sendTxToL1 call was made
|
62
|
+
* @param value wei in L1 message
|
63
|
+
* @param data abi-encoded L1 message data
|
64
|
+
*/
|
32
65
|
function executeTransaction(
|
33
66
|
bytes32[] calldata proof,
|
34
67
|
uint256 index,
|
@@ -41,6 +74,17 @@ interface IOutbox {
|
|
41
74
|
bytes calldata data
|
42
75
|
) external;
|
43
76
|
|
77
|
+
/**
|
78
|
+
* @dev function used to simulate the result of a particular function call from the outbox
|
79
|
+
* it is useful for things such as gas estimates. This function includes all costs except for
|
80
|
+
* proof validation (which can be considered offchain as a somewhat of a fixed cost - it's
|
81
|
+
* not really a fixed cost, but can be treated as so with a fixed overhead for gas estimation).
|
82
|
+
* We can't include the cost of proof validation since this is intended to be used to simulate txs
|
83
|
+
* that are included in yet-to-be confirmed merkle roots. The simulation entrypoint could instead pretend
|
84
|
+
* to confirm a pending merkle root, but that would be less practical for integrating with tooling.
|
85
|
+
* It is only possible to trigger it when the msg sender is address zero, which should be impossible
|
86
|
+
* unless under simulation in an eth_call or eth_estimateGas
|
87
|
+
*/
|
44
88
|
function executeTransactionSimulation(
|
45
89
|
uint256 index,
|
46
90
|
address l2Sender,
|
@@ -52,7 +96,11 @@ interface IOutbox {
|
|
52
96
|
bytes calldata data
|
53
97
|
) external;
|
54
98
|
|
55
|
-
|
99
|
+
/**
|
100
|
+
* @param index Merkle path to message
|
101
|
+
* @return true if the message has been spent
|
102
|
+
*/
|
103
|
+
function isSpent(uint256 index) external view returns (bool);
|
56
104
|
|
57
105
|
function calculateItemHash(
|
58
106
|
address l2Sender,
|