@@ -9,6 +9,8 @@ import "./PacayaAnchor.sol";
9
9
/// @custom:security-contact [email protected]
10
10
abstract contract ShastaAnchor is PacayaAnchor {
11
11
error InvalidForkHeight ();
12
+ error NonZeroAnchorStateRoot ();
13
+ error ZeroAnchorStateRoot ();
12
14
13
15
// The v4Anchor's transaction gas limit, this value must be enforced by the node and prover.
14
16
// When there are 16 signals in v4Anchor's parameter, the estimated gas cost is actually
@@ -30,17 +32,19 @@ abstract contract ShastaAnchor is PacayaAnchor {
30
32
shastaForkHeight = _shastaForkHeight;
31
33
}
32
34
33
- /// @notice Anchors the latest L1 block details to L2 for cross-layer
35
+ /// @notice This function anchors the latest L1 block details to L2, enabling cross-layer
34
36
/// message verification.
35
- /// @dev The gas limit for this transaction must be set to 1,000,000 gas.
36
- /// @dev This function can be called freely as the golden touch private key is publicly known,
37
- /// but the Taiko node guarantees the first transaction of each block is always this anchor
38
- /// transaction, and any subsequent calls will revert with L2_PUBLIC_INPUT_HASH_MISMATCH.
39
- /// @param _anchorBlockId The `anchorBlockId` value in this block's metadata.
40
- /// @param _anchorStateRoot The state root for the L1 block with id equals `_anchorBlockId`.
41
- /// @param _parentGasUsed The gas used in the parent block.
42
- /// @param _baseFeeConfig The base fee configuration.
43
- /// @param _signalSlots The signal slots to mark as received.
37
+ /// @dev The gas limit for this transaction is required to be set to 1,000,000 gas.
38
+ /// @dev Although this function can be invoked freely due to the public availability of the
39
+ /// golden touch private key,
40
+ /// the Taiko node ensures that the first transaction of each block is always this anchor
41
+ /// transaction. Any subsequent calls will be reverted with L2_PUBLIC_INPUT_HASH_MISMATCH.
42
+ /// @param _anchorBlockId This is the `anchorBlockId` value in the metadata of this block.
43
+ /// @param _anchorStateRoot This is the state root for the L1 block with an id equal to
44
+ /// `_anchorBlockId`.
45
+ /// @param _parentGasUsed This is the amount of gas used in the parent block.
46
+ /// @param _baseFeeConfig This is the configuration for the base fee.
47
+ /// @param _signalSlots These are the signal slots to be marked as received.
44
48
function v4Anchor (
45
49
uint64 _anchorBlockId ,
46
50
bytes32 _anchorStateRoot ,
@@ -50,8 +54,6 @@ abstract contract ShastaAnchor is PacayaAnchor {
50
54
bytes32 [] calldata _signalSlots
51
55
)
52
56
external
53
- nonZeroBytes32 (_anchorStateRoot)
54
- nonZeroValue (_anchorBlockId)
55
57
nonZeroValue (_baseFeeConfig.gasIssuancePerSecond)
56
58
nonZeroValue (_baseFeeConfig.adjustmentQuotient)
57
59
onlyGoldenTouch
@@ -62,10 +64,20 @@ abstract contract ShastaAnchor is PacayaAnchor {
62
64
uint256 parentId = block .number - 1 ;
63
65
_verifyAndUpdatePublicInputHash (parentId);
64
66
_verifyBaseFeeAndUpdateGasExcess (_parentGasUsed, _baseFeeConfig);
65
- _syncChainData (_anchorBlockId, _anchorStateRoot);
66
67
_updateParentHashAndTimestamp (parentId);
67
68
68
- signalService.receiveSignals (_signalSlots);
69
+ if (_anchorBlockId == 0 ) {
70
+ // This block must not be the last block in the batch.
71
+ require (_anchorStateRoot == 0 , NonZeroAnchorStateRoot ());
72
+ } else {
73
+ // This block must be the last block in the batch.
74
+ require (_anchorStateRoot != 0 , ZeroAnchorStateRoot ());
75
+ _syncChainData (_anchorBlockId, _anchorStateRoot);
76
+ }
77
+
78
+ if (_signalSlots.length != 0 ) {
79
+ signalService.receiveSignals (_signalSlots);
80
+ }
69
81
70
82
// We need to add one SSTORE from non-zero to non-zero (5000), one addition (3), and one
71
83
// subtraction (3).
0 commit comments