-
Notifications
You must be signed in to change notification settings - Fork 2.2k
/
Copy pathTaikoL1.sol
312 lines (283 loc) · 10.5 KB
/
TaikoL1.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
import "../common/EssentialContract.sol";
import "./libs/LibData.sol";
import "./libs/LibProposing.sol";
import "./libs/LibProving.sol";
import "./libs/LibVerifying.sol";
import "./TaikoEvents.sol";
import "./ITaikoL1.sol";
/// @title TaikoL1
/// @notice This contract serves as the "base layer contract" of the Taiko protocol, providing
/// functionalities for proposing, proving, and verifying blocks. The term "base layer contract"
/// means that although this is usually deployed on L1, it can also be deployed on L2s to create
/// L3 "inception layers". The contract also handles the deposit and withdrawal of Taiko tokens
/// and Ether. Additionally, this contract doesn't hold any Ether. Ether deposited to L2 are held
/// by the Bridge contract.
/// @dev Labeled in AddressResolver as "taiko"
/// @custom:security-contact [email protected]
contract TaikoL1 is EssentialContract, ITaikoL1, TaikoEvents {
/// @notice The TaikoL1 state.
TaikoData.State public state;
uint256[50] private __gap;
error L1_FORK_ERROR();
error L1_INVALID_PARAMS();
modifier whenProvingNotPaused() {
if (state.slotB.provingPaused) revert LibProving.L1_PROVING_PAUSED();
_;
}
modifier emitEventForClient() {
_;
emit StateVariablesUpdated(state.slotB);
}
/// @notice Initializes the contract.
/// @param _owner The owner of this contract. msg.sender will be used if this value is zero.
/// @param _rollupAddressManager The address of the {AddressManager} contract.
/// @param _genesisBlockHash The block hash of the genesis block.
/// @param _toPause true to pause the contract by default.
function init(
address _owner,
address _rollupAddressManager,
bytes32 _genesisBlockHash,
bool _toPause
)
external
initializer
{
__Essential_init(_owner, _rollupAddressManager);
LibUtils.init(state, getConfig(), _genesisBlockHash);
if (_toPause) _pause();
}
function init2() external onlyOwner reinitializer(2) {
// reset some previously used slots for future reuse
state.slotB.__reservedB1 = 0;
state.slotB.__reservedB2 = 0;
state.slotB.__reservedB3 = 0;
state.__reserve1 = 0;
}
/// @inheritdoc ITaikoL1
function proposeBlock(
bytes calldata _params,
bytes calldata _txList
)
external
payable
onlyFromOptionalNamed(LibStrings.B_BLOCK_PROPOSER)
whenNotPaused
nonReentrant
emitEventForClient
returns (TaikoData.BlockMetadata memory meta_, TaikoData.EthDeposit[] memory deposits_)
{
TaikoData.Config memory config = getConfig();
(meta_,) = LibProposing.proposeBlock(state, config, this, _params, _txList);
if (meta_.id >= config.ontakeForkHeight) revert L1_FORK_ERROR();
deposits_ = new TaikoData.EthDeposit[](0);
}
function proposeBlockV2(
bytes calldata _params,
bytes calldata _txList
)
external
onlyFromOptionalNamed(LibStrings.B_BLOCK_PROPOSER)
whenNotPaused
nonReentrant
emitEventForClient
returns (TaikoData.BlockMetadataV2 memory meta_)
{
TaikoData.Config memory config = getConfig();
(, meta_) = LibProposing.proposeBlock(state, config, this, _params, _txList);
if (meta_.id < config.ontakeForkHeight) revert L1_FORK_ERROR();
}
/// @inheritdoc ITaikoL1
function proposeBlocksV2(
bytes[] calldata _paramsArr,
bytes[] calldata _txListArr
)
external
onlyFromOptionalNamed(LibStrings.B_BLOCK_PROPOSER)
whenNotPaused
nonReentrant
emitEventForClient
returns (TaikoData.BlockMetadataV2[] memory metaArr_)
{
TaikoData.Config memory config = getConfig();
(, metaArr_) = LibProposing.proposeBlocks(state, config, this, _paramsArr, _txListArr);
for (uint256 i; i < metaArr_.length; ++i) {
if (metaArr_[i].id < config.ontakeForkHeight) revert L1_FORK_ERROR();
}
}
/// @inheritdoc ITaikoL1
function proveBlock(
uint64 _blockId,
bytes calldata _input
)
external
whenNotPaused
whenProvingNotPaused
nonReentrant
emitEventForClient
{
LibProving.proveBlock(state, getConfig(), this, _blockId, _input);
}
/// @inheritdoc ITaikoL1
function proveBlocks(
uint64[] calldata _blockIds,
bytes[] calldata _inputs,
bytes calldata _batchProof
)
external
whenNotPaused
whenProvingNotPaused
nonReentrant
emitEventForClient
{
LibProving.proveBlocks(state, getConfig(), this, _blockIds, _inputs, _batchProof);
}
/// @inheritdoc ITaikoL1
function verifyBlocks(uint64 _maxBlocksToVerify)
external
whenNotPaused
whenProvingNotPaused
nonReentrant
emitEventForClient
{
LibVerifying.verifyBlocks(state, getConfig(), this, _maxBlocksToVerify);
}
/// @inheritdoc ITaikoL1
function pauseProving(bool _pause) external {
_authorizePause(msg.sender, _pause);
LibProving.pauseProving(state, _pause);
}
/// @inheritdoc ITaikoL1
function depositBond(uint256 _amount) external whenNotPaused {
LibBonds.depositBond(state, this, _amount);
}
/// @inheritdoc ITaikoL1
function withdrawBond(uint256 _amount) external whenNotPaused {
LibBonds.withdrawBond(state, this, _amount);
}
/// @notice Gets the current bond balance of a given address.
/// @return The current bond balance.
function bondBalanceOf(address _user) external view returns (uint256) {
return LibBonds.bondBalanceOf(state, _user);
}
/// @inheritdoc ITaikoL1
function getVerifiedBlockProver(uint64 _blockId) external view returns (address prover_) {
return LibVerifying.getVerifiedBlockProver(state, getConfig(), _blockId);
}
/// @notice Gets the details of a block.
/// @param _blockId Index of the block.
/// @return blk_ The block.
function getBlock(uint64 _blockId) external view returns (TaikoData.Block memory blk_) {
(TaikoData.BlockV2 memory blk,) = LibUtils.getBlock(state, getConfig(), _blockId);
blk_ = LibData.blockV2toV1(blk);
}
/// @notice Gets the details of a block.
/// @param _blockId Index of the block.
/// @return blk_ The block.
function getBlockV2(uint64 _blockId) external view returns (TaikoData.BlockV2 memory blk_) {
(blk_,) = LibUtils.getBlock(state, getConfig(), _blockId);
}
/// @notice Gets the state transition for a specific block.
/// @param _blockId Index of the block.
/// @param _parentHash Parent hash of the block.
/// @return The state transition data of the block.
function getTransition(
uint64 _blockId,
bytes32 _parentHash
)
external
view
returns (TaikoData.TransitionState memory)
{
return LibUtils.getTransition(state, getConfig(), _blockId, _parentHash);
}
/// @notice Gets the state transition for a specific block.
/// @param _blockId Index of the block.
/// @param _tid The transition id.
/// @return The state transition data of the block.
function getTransition(
uint64 _blockId,
uint32 _tid
)
external
view
returns (TaikoData.TransitionState memory)
{
return LibUtils.getTransition(state, getConfig(), _blockId, _tid);
}
/// @notice Returns information about the last verified block.
/// @return blockId_ The last verified block's ID.
/// @return blockHash_ The last verified block's blockHash.
/// @return stateRoot_ The last verified block's stateRoot.
/// @return verifiedAt_ The timestamp this block is verified at.
function getLastVerifiedBlock()
external
view
returns (uint64 blockId_, bytes32 blockHash_, bytes32 stateRoot_, uint64 verifiedAt_)
{
blockId_ = state.slotB.lastVerifiedBlockId;
(blockHash_, stateRoot_, verifiedAt_) = LibUtils.getBlockInfo(state, getConfig(), blockId_);
}
/// @notice Returns information about the last synchronized block.
/// @return blockId_ The last verified block's ID.
/// @return blockHash_ The last verified block's blockHash.
/// @return stateRoot_ The last verified block's stateRoot.
/// @return verifiedAt_ The timestamp this block is verified at.
function getLastSyncedBlock()
external
view
returns (uint64 blockId_, bytes32 blockHash_, bytes32 stateRoot_, uint64 verifiedAt_)
{
blockId_ = state.slotA.lastSyncedBlockId;
(blockHash_, stateRoot_, verifiedAt_) = LibUtils.getBlockInfo(state, getConfig(), blockId_);
}
/// @notice Gets the state variables of the TaikoL1 contract.
/// @dev This method can be deleted once node/client stops using it.
/// @return State variables stored at SlotA.
/// @return State variables stored at SlotB.
function getStateVariables()
external
view
returns (TaikoData.SlotA memory, TaikoData.SlotB memory)
{
return (state.slotA, state.slotB);
}
/// @inheritdoc EssentialContract
function unpause() public override {
super.unpause(); // permission checked inside
state.slotB.lastUnpausedAt = uint64(block.timestamp);
}
/// @inheritdoc ITaikoL1
function getConfig() public pure virtual returns (TaikoData.Config memory) {
return TaikoData.Config({
chainId: LibNetwork.TAIKO_MAINNET,
blockMaxProposals: 324_000, // = 7200 * 45
blockRingBufferSize: 360_000, // = 7200 * 50
maxBlocksToVerify: 16,
blockMaxGasLimit: 240_000_000,
livenessBond: 125e18, // 125 Taiko token
stateRootSyncInternal: 16,
maxAnchorHeightOffset: 64,
baseFeeConfig: TaikoData.BaseFeeConfig({
adjustmentQuotient: 8,
sharingPctg: 75,
gasIssuancePerSecond: 5_000_000,
minGasExcess: 1_340_000_000,
maxGasIssuancePerBlock: 600_000_000 // two minutes
}),
ontakeForkHeight: 374_400 // = 7200 * 52
});
}
/// @dev chain_pauser is supposed to be a cold wallet.
function _authorizePause(
address,
bool
)
internal
view
virtual
override
onlyFromOwnerOrNamed(LibStrings.B_CHAIN_WATCHDOG)
{ }
}