mega-evm 1.6.0

The evm tailored for the MegaETH
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
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
//! Block-level resource limit enforcement for `MegaETH`.
//!
//! This module provides comprehensive limit tracking and enforcement for block-level resources
//! in the `MegaETH` EVM. It implements a two-phase checking system to optimize block construction
//! while preventing spam attacks and ensuring fair resource allocation.
//!
//! # Overview
//!
//! `MegaEVM` enforces **6 types of limits**, each with both **transaction-level** and
//! **block-level** variants:
//!
//! 1. **Gas Limit** - Traditional EVM gas consumption
//! 2. **Transaction Size Limit** - EIP-2718 encoded transaction size
//! 3. **Data Availability (DA) Size Limit** - Compressed DA size
//! 4. **Compute Gas Limit** - Actual computational cost (separate from standard gas)
//! 5. **Data Size Limit** - Total execution data generated
//! 6. **KV Update Limit** - Storage operations count
//!
//! # Two-Phase Checking Strategy
//!
//! ## Phase 1: Pre-execution Checks (Limits 1-3)
//!
//! **When**: Before transaction execution
//! **What**: Validates gas limit, transaction size, and DA size
//! **Purpose**: Fast rejection of oversized transactions without expensive execution
//!
//! ### Transaction-level Violations
//! - **Error**: [`MegaTxLimitExceededError`]
//! - **Action**: Transaction is **rejected permanently** (invalid transaction)
//! - **Reason**: Transaction exceeds individual limit (e.g., gas > `tx_gas_limit`)
//! - **Example**: A transaction declares 50M gas when limit is 30M gas
//!
//! ### Block-level Violations
//! - **Error**: [`MegaBlockLimitExceededError`] or
//!   [`BlockValidationError::TransactionGasLimitMoreThanAvailableBlockGas`]
//! - **Action**: Transaction is **skipped**, try next transaction
//! - **Reason**: Including this transaction would exceed block capacity
//! - **Example**: Block has 5M gas remaining, transaction needs 10M gas
//!
//! ## Phase 2: Post-execution Checks (Limits 4-6)
//!
//! **When**: After transaction execution, before state commitment
//! **What**: Validates compute gas, data size, and KV updates
//! **Purpose**: Enforce limits based on actual execution results
//!
//! ### Transaction-level Enforcement (During Execution)
//! - **Location**: Enforced in [`crate::evm::limit::AdditionalLimit`]
//! - **Behavior**: Transaction halts with `OutOfGas`, remaining gas preserved
//! - **Result**: Transaction fails (status=0) but is **still included in block**
//! - **Reason**: Failed transactions consume resources and must be recorded on-chain
//!
//! ### Block-level Enforcement (Before Next Transaction)
//! - The first transaction that causes the block to exceed limits is **allowed to execute and be
//!   included**
//! - **Pre-execution check**: Before executing the next transaction, check if block limit has
//!   already been exceeded
//! - **Action**: If limit already exceeded, reject transaction before execution
//! - **Reason**: Maximize block utilization by not wasting valid transaction execution
//! - **Example**: Block has 10MB data limit. TX1 uses 6MB (included), TX2 uses 8MB (included, total
//!   14MB exceeds limit), TX3 is rejected before execution
//!
//! # Architecture
//!
//! The module consists of two main types:
//!
//! - [`BlockLimits`]: Configuration struct defining all limit thresholds
//! - [`BlockLimiter`]: Stateful tracker that enforces limits and accumulates resource usage
//!
//! # Limit Types
//!
//! ## Pre-execution Limits (Checked before execution)
//!
//! 1. **Gas Limit**
//!    - Tx-level: `tx_gas_limit` - Maximum gas per transaction
//!    - Block-level: `block_gas_limit` - Total gas available in block
//!
//! 2. **Transaction Size Limit**
//!    - Tx-level: `tx_encode_size_limit` - Maximum encoded transaction size
//!    - Block-level: `block_txs_encode_size_limit` - Total uncompressed transaction size in block
//!
//! 3. **Data Availability Size Limit**
//!    - Tx-level: `tx_da_size_limit` - Maximum DA size per transaction
//!    - Block-level: `block_da_size_limit` - Total compressed DA size in block
//!    - **Note**: Deposit transactions are exempt from DA size limit checks
//!
//! ## Post-execution Limits (Checked during/after execution)
//!
//! 4. **Compute Gas Limit**
//!    - Tx-level: `tx_compute_gas_limit` - Maximum compute gas per transaction
//!    - Block-level: `block_compute_gas_limit` - Total compute gas in block
//!
//! 5. **Data Size Limit**
//!    - Tx-level: `tx_data_limit` - Maximum data per transaction
//!    - Block-level: `block_txs_data_limit` - Total execution data in block
//!    - Includes: tx data, logs, storage writes, account updates, contract code
//!
//! 6. **KV Update Limit**
//!    - Tx-level: `tx_kv_update_limit` - Maximum storage updates per transaction
//!    - Block-level: `block_kv_update_limit` - Total storage updates in block
//!    - Tracks: SSTORE operations and account updates
//!
//! # Deposit Transaction Exemptions
//!
//! Deposit transactions (Optimism Layer 1 to Layer 2 deposits) receive special treatment:
//!
//! - **DA Size Limit Exemption**: Deposit transactions are exempt from both transaction-level and
//!   block-level Data Availability size limit checks during pre-execution validation
//! - **Rationale**: Deposit transactions are trustless L1→L2 messages that cannot be censored. They
//!   must be included in blocks regardless of their DA size to maintain bridge integrity
//! - **Tracking**: While exempt from limit checks, deposit DA sizes are still tracked and
//!   accumulated in block DA usage counters for monitoring purposes
//! - **Other Limits**: Deposit transactions are still subject to all other limits (gas, tx size,
//!   compute gas, data size, KV updates)
//!
//! # Block Building Workflow
//!
//! For each transaction in the mempool:
//!
//! 1. **Pre-execution check** - [`BlockLimiter::pre_execution_check`]
//!    - If tx-level violation → Reject permanently
//!    - If block-level violation → Skip, try next transaction
//!
//! 2. **Execute transaction** - [`crate::MegaBlockExecutor::execute_mega_transaction`]
//!    - During execution, tx-level limits (4-6) are enforced in EVM
//!    - If exceeded → Transaction fails but continues to step 3
//!
//! 3. **Post-execution update** - [`BlockLimiter::post_execution_update`]
//!    - Accumulates resource usage from the executed transaction into block-level counters
//!    - Does not validate post-execution limits; over-limit enforcement happens before admitting
//!      the next transaction in [`BlockLimiter::pre_execution_check`]
//!
//! 4. **Commit transaction** - [`crate::MegaBlockExecutor::commit_execution_outcome`]
//!    - Include in block (with success or failed receipt)
//!    - Update block usage counters
//!
//! # Configuration
//!
//! ## For EQUIVALENCE Specification (Optimism Isthmus Compatible)
//!
//! ```rust,ignore
//! let limits = BlockLimits::no_limits()
//!     .with_block_gas_limit(block_env.gas_limit)
//!     .fit_equivalence();
//! ```
//!
//! ## For `MINI_REX` Specification (Enhanced with Additional Limits)
//!
//! ```rust,ignore
//! use mega_evm::constants::mini_rex;
//!
//! let limits = BlockLimits::no_limits()
//!     .with_block_gas_limit(block_env.gas_limit)
//!     .fit_mini_rex();  // Sets all MINI_REX limits automatically
//! ```
//!
//! Or configure manually:
//!
//! ```rust,ignore
//! let limits = BlockLimits::no_limits()
//!     .with_block_gas_limit(block_env.gas_limit)
//!     .with_tx_compute_gas_limit(mini_rex::TX_COMPUTE_GAS_LIMIT)
//!     .with_block_txs_data_limit(mini_rex::BLOCK_DATA_LIMIT)
//!     .with_block_kv_update_limit(mini_rex::BLOCK_KV_UPDATE_LIMIT);
//! ```
//!
//! # Error Handling
//!
//! ## Transaction-level Errors (Permanent Rejection)
//! - [`MegaTxLimitExceededError::TransactionGasLimit`] - Gas limit too high
//! - [`MegaTxLimitExceededError::TransactionEncodeSizeLimit`] - Transaction too large
//! - [`MegaTxLimitExceededError::DataAvailabilitySizeLimit`] - DA size too large
//!
//! ## Block-level Errors (Skip and Try Next)
//! - [`MegaBlockLimitExceededError::ComputeGasLimit`] - Would exceed block compute gas
//! - [`MegaBlockLimitExceededError::TransactionDataLimit`] - Would exceed block data limit
//! - [`MegaBlockLimitExceededError::KVUpdateLimit`] - Would exceed block KV updates
//! - [`MegaBlockLimitExceededError::TransactionEncodeSizeLimit`] - Would exceed block tx size
//! - [`MegaBlockLimitExceededError::DataAvailabilitySizeLimit`] - Would exceed block DA size
//! - [`BlockValidationError::TransactionGasLimitMoreThanAvailableBlockGas`] - Insufficient gas
//!
//! # See Also
//!
//! - [`crate::evm::limit`] - Transaction-level limit enforcement during execution
//! - [`crate::MegaBlockExecutor`] - Block executor that orchestrates limit checks

#[cfg(not(feature = "std"))]
use alloc as std;
use std::boxed::Box;

use alloy_consensus::Transaction;
use alloy_evm::{
    block::{BlockExecutionError, BlockValidationError},
    RecoveredTx,
};
use alloy_primitives::TxHash;
use op_revm::transaction::deposit::DEPOSIT_TRANSACTION_TYPE;

use crate::{
    BlockMegaTransactionOutcome, EvmTxRuntimeLimits, MegaBlockLimitExceededError, MegaHardfork,
    MegaTransactionExt, MegaTxLimitExceededError,
};

/// Configuration for block-level resource limits. The block-level resource limits are associated
/// with a specific `MegaHardfork` instead of a `MegaSpecId`. In constrast, `EvmTxRuntimeLimits` is
/// associated with a `MegaSpecId`.
///
/// This struct defines the thresholds for various resource limits that govern transaction
/// inclusion and block construction. Limits are categorized into two groups:
///
/// 1. **Pre-execution limits**: Checked before transaction execution (gas, size, DA size)
/// 2. **Post-execution limits**: Checked after execution (data size, KV updates)
///
/// # Default Behavior
///
/// By default, most limits are set to `u64::MAX` (effectively unlimited) except for:
/// - `block_txs_data_limit`: Set to [`crate::constants::mini_rex::BLOCK_DATA_LIMIT`]
/// - `block_kv_update_limit`: Set to [`crate::constants::mini_rex::BLOCK_KV_UPDATE_LIMIT`]
/// - `block_gas_limit`: Auto-set from the EVM block environment (cannot be manually configured)
///
/// # Builder Pattern
///
/// Use builder methods to configure specific limits:
///
/// ```rust,ignore
/// let limits = BlockLimits::default()
///     .with_tx_gas_limit(15_000_000)
///     .with_block_txs_encode_size_limit(1_000_000)
///     .with_block_txs_data_limit(5_000);
/// ```
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct BlockLimits {
    /// Maximum gas limit for a single transaction.
    ///
    /// Transactions with gas limits exceeding this value will be rejected with
    /// [`MegaTxLimitExceededError::TransactionGasLimit`].
    pub tx_gas_limit: u64,

    /// Total gas limit for the block.
    ///
    /// Transactions that would cause the cumulative block gas to exceed this limit are rejected
    /// with [`BlockValidationError::TransactionGasLimitMoreThanAvailableBlockGas`].
    pub block_gas_limit: u64,

    /// Maximum encoded size (in bytes) for a single transaction.
    ///
    /// This limit applies to the transaction's EIP-2718 encoded size. Transactions exceeding
    /// this size will be rejected with [`MegaTxLimitExceededError::TransactionEncodeSizeLimit`].
    ///
    /// Default: `u64::MAX` (effectively unlimited)
    pub tx_encode_size_limit: u64,

    /// Maximum cumulative size (in bytes) of all transaction bodies in a block.
    ///
    /// This limit applies to the **uncompressed** transaction size. For compressed data
    /// availability limits, see [`block_da_size_limit`](Self::block_da_size_limit).
    ///
    /// Transactions that would cause the cumulative block transaction size to exceed this
    /// limit are rejected with [`MegaBlockLimitExceededError::TransactionEncodeSizeLimit`].
    ///
    /// Default: `u64::MAX` (effectively unlimited)
    pub block_txs_encode_size_limit: u64,

    /// Maximum data availability size (in bytes) for a single transaction.
    ///
    /// This represents the compressed size for data availability purposes. Transactions
    /// exceeding this size will be rejected with
    /// [`MegaTxLimitExceededError::DataAvailabilitySizeLimit`].
    ///
    /// Default: `u64::MAX` (effectively unlimited)
    pub tx_da_size_limit: u64,

    /// Maximum cumulative data availability size (in bytes) for all transactions in a block.
    ///
    /// This applies to the **compressed** transaction size for data availability. For
    /// uncompressed transaction body limits, see
    /// [`block_txs_encode_size_limit`](Self::block_txs_encode_size_limit).
    ///
    /// Transactions that would cause the cumulative block DA size to exceed this limit are
    /// rejected with [`MegaBlockLimitExceededError::DataAvailabilitySizeLimit`].
    ///
    /// Default: `u64::MAX` (effectively unlimited)
    pub block_da_size_limit: u64,

    /// Maximum data size of a single transaction's execution outcome, i.e., encoded transaction
    /// object, encoded state changes, logs, etc. The data will need to be saved and transmitted
    /// over network.
    pub tx_data_limit: u64,

    /// Maximum cumulative data size (in bytes) of all transactions' execution outcomes from block
    /// execution.
    ///
    /// This limit is checked **after** transaction execution but **before** committing state
    /// changes. It tracks the total data produced by all transactions in the block, including
    /// logs, return data, and other execution artifacts.
    ///
    /// Transactions that would cause the cumulative block data to exceed this limit are
    /// rejected with [`MegaBlockLimitExceededError::TransactionDataLimit`], and their state
    /// changes are **not committed**.
    ///
    /// Note: Transaction-level data limits are enforced separately in the `MegaEVM`.
    /// Transactions exceeding transaction-level limits may still be included but marked
    /// as failed.
    pub block_txs_data_limit: u64,

    /// Maximum key-value updates for a single transaction.
    pub tx_kv_update_limit: u64,

    /// Maximum cumulative key-value updates allowed in a block.
    ///
    /// This limit is checked **after** transaction execution but **before** committing state
    /// changes. It tracks the total number of storage slot updates (SSTORE operations) across
    /// all transactions in the block.
    ///
    /// Transactions that would cause the cumulative KV updates to exceed this limit are
    /// rejected with [`MegaBlockLimitExceededError::KVUpdateLimit`], and their state changes
    /// are **not committed**.
    ///
    /// Note: Transaction-level KV update limits are enforced separately in the `MegaEVM`.
    /// Transactions exceeding transaction-level limits may still be included but marked
    /// as failed.
    pub block_kv_update_limit: u64,

    /// Maximum compute gas limit for a single transaction.
    pub tx_compute_gas_limit: u64,

    /// Maximum cumulative compute gas limit for all transactions in a block.
    ///
    /// This limit is checked **after** transaction execution but **before** committing state
    /// changes. It tracks the total compute gas consumed by all transactions in the block.
    ///
    /// Transactions that would cause the cumulative block compute gas to exceed this limit are
    /// rejected with [`MegaBlockLimitExceededError::ComputeGasLimit`], and their state changes
    /// are **not committed**.
    pub block_compute_gas_limit: u64,

    /// Maximum state growth limit for a single transaction.
    pub tx_state_growth_limit: u64,

    /// Maximum cumulative state growth limit for all transactions in a block.
    ///
    /// This limit is checked **after** transaction execution but **before** committing state
    /// changes. It tracks the total state growth consumed by all transactions in the block.
    ///
    /// Transactions that would cause the cumulative block state growth to exceed this limit are
    /// rejected with [`MegaBlockLimitExceededError::StateGrowthLimit`], and their state changes
    /// are **not committed**.
    pub block_state_growth_limit: u64,

    /// Compute gas limit when accessing block environment data.
    ///
    /// When a transaction accesses volatile block environment data (e.g., TIMESTAMP, COINBASE),
    /// the compute gas is capped to this limit to prevent `DoS` attacks.
    pub block_env_access_compute_gas_limit: u64,

    /// Compute gas limit when accessing oracle data.
    ///
    /// When a transaction accesses the oracle contract, the compute gas is capped to this
    /// limit to prevent `DoS` attacks.
    pub oracle_access_compute_gas_limit: u64,
}

impl BlockLimits {
    /// Creates a new block limits instance with no limits.
    pub fn no_limits() -> Self {
        Self {
            tx_gas_limit: u64::MAX,
            block_gas_limit: u64::MAX,
            tx_encode_size_limit: u64::MAX,
            block_txs_encode_size_limit: u64::MAX,
            tx_da_size_limit: u64::MAX,
            block_da_size_limit: u64::MAX,
            tx_data_limit: u64::MAX,
            block_txs_data_limit: u64::MAX,
            tx_kv_update_limit: u64::MAX,
            block_kv_update_limit: u64::MAX,
            tx_compute_gas_limit: u64::MAX,
            block_compute_gas_limit: u64::MAX,
            tx_state_growth_limit: u64::MAX,
            block_state_growth_limit: u64::MAX,
            block_env_access_compute_gas_limit: u64::MAX,
            oracle_access_compute_gas_limit: u64::MAX,
        }
    }

    /// Creates a new block limits instance from a hardfork and a block gas limit.
    pub fn from_hardfork_and_block_gas_limit(hardfork: MegaHardfork, block_gas_limit: u64) -> Self {
        let spec = hardfork.spec_id();
        let tx_runtime_limits = EvmTxRuntimeLimits::from_spec(spec);
        let limits = Self::no_limits()
            .with_tx_runtime_limits(tx_runtime_limits)
            .with_block_gas_limit(block_gas_limit);
        match hardfork {
            MegaHardfork::Rex |
            MegaHardfork::Rex1 |
            MegaHardfork::Rex2 |
            MegaHardfork::Rex3 |
            MegaHardfork::Rex4 |
            MegaHardfork::Rex5 => Self {
                block_txs_data_limit: crate::constants::mini_rex::BLOCK_DATA_LIMIT,
                block_kv_update_limit: crate::constants::mini_rex::BLOCK_KV_UPDATE_LIMIT,
                block_state_growth_limit: crate::constants::rex::BLOCK_STATE_GROWTH_LIMIT,
                ..limits
            },
            MegaHardfork::MiniRex | MegaHardfork::MiniRex2 => Self {
                block_txs_data_limit: crate::constants::mini_rex::BLOCK_DATA_LIMIT,
                block_kv_update_limit: crate::constants::mini_rex::BLOCK_KV_UPDATE_LIMIT,
                ..limits
            },
            MegaHardfork::MiniRex1 => limits,
        }
    }
}

impl BlockLimits {
    /// Sets the related fields
    pub fn with_tx_runtime_limits(mut self, limits: EvmTxRuntimeLimits) -> Self {
        self.tx_data_limit = limits.tx_data_size_limit;
        self.tx_kv_update_limit = limits.tx_kv_updates_limit;
        self.tx_compute_gas_limit = limits.tx_compute_gas_limit;
        self.tx_state_growth_limit = limits.tx_state_growth_limit;
        self.block_env_access_compute_gas_limit = limits.block_env_access_compute_gas_limit;
        self.oracle_access_compute_gas_limit = limits.oracle_access_compute_gas_limit;
        self
    }

    /// Set a custom transaction gas limit.
    ///
    /// This is a builder method that consumes self and returns a new instance
    /// with the specified transaction gas limit. Transactions with gas limits
    /// exceeding this value will be rejected.
    ///
    /// # Parameters
    ///
    /// - `limit`: Maximum gas limit for a single transaction
    ///
    /// # Example
    ///
    /// ```rust,ignore
    /// let limits = BlockLimits::default()
    ///     .with_tx_gas_limit(15_000_000);
    /// ```
    pub fn with_tx_gas_limit(mut self, limit: u64) -> Self {
        self.tx_gas_limit = limit;
        self
    }

    /// Set a custom block gas limit.
    ///
    /// **Warning**: This setting is **overridden** during block executor initialization.
    /// The block gas limit is automatically set from the EVM block environment's gas limit.
    /// This method exists for testing purposes only.
    ///
    /// # Parameters
    ///
    /// - `limit`: Block gas limit (will be overridden at runtime)
    pub fn with_block_gas_limit(mut self, limit: u64) -> Self {
        self.block_gas_limit = limit;
        self
    }

    /// Set a custom transaction encode size limit.
    ///
    /// This is a builder method that consumes self and returns a new instance
    /// with the specified transaction encode size limit.
    pub fn with_tx_encode_size_limit(mut self, limit: u64) -> Self {
        self.tx_encode_size_limit = limit;
        self
    }

    /// Set a custom block transactions encode size limit.
    ///
    /// This is a builder method that consumes self and returns a new instance
    /// with the specified block transactions encode size limit.
    pub fn with_block_txs_encode_size_limit(mut self, limit: u64) -> Self {
        self.block_txs_encode_size_limit = limit;
        self
    }

    /// Set a custom transaction data availability size limit.
    ///
    /// This is a builder method that consumes self and returns a new instance
    /// with the specified transaction data availability size limit.
    pub fn with_tx_da_size_limit(mut self, limit: u64) -> Self {
        self.tx_da_size_limit = limit;
        self
    }

    /// Set a custom block data availability size limit.
    ///
    /// This is a builder method that consumes self and returns a new instance
    /// with the specified data availability size limit.
    pub fn with_block_da_size_limit(mut self, limit: u64) -> Self {
        self.block_da_size_limit = limit;
        self
    }

    /// Set a custom transaction data limit.
    ///
    /// This is a builder method that consumes self and returns a new instance
    /// with the specified transaction data limit.
    pub fn with_tx_data_limit(mut self, limit: u64) -> Self {
        self.tx_data_limit = limit;
        self
    }

    /// Set a custom block transactions data limit.
    ///
    /// This is a builder method that consumes self and returns a new instance
    /// with the specified block transactions data limit.
    pub fn with_block_txs_data_limit(mut self, limit: u64) -> Self {
        self.block_txs_data_limit = limit;
        self
    }

    /// Set a custom transaction KV update limit.
    ///
    /// This is a builder method that consumes self and returns a new instance
    /// with the specified transaction KV update limit.
    pub fn with_tx_kv_update_limit(mut self, limit: u64) -> Self {
        self.tx_kv_update_limit = limit;
        self
    }

    /// Set a custom block KV update limit.
    ///
    /// This is a builder method that consumes self and returns a new instance
    /// with the specified KV update limit.
    pub fn with_block_kv_update_limit(mut self, limit: u64) -> Self {
        self.block_kv_update_limit = limit;
        self
    }

    /// Set a custom transaction compute gas limit.
    ///
    /// This is a builder method that consumes self and returns a new instance
    /// with the specified transaction compute gas limit.
    pub fn with_tx_compute_gas_limit(mut self, limit: u64) -> Self {
        self.tx_compute_gas_limit = limit;
        self
    }

    /// Set a custom block compute gas limit.
    ///
    /// This is a builder method that consumes self and returns a new instance
    /// with the specified block compute gas limit.
    pub fn with_block_compute_gas_limit(mut self, limit: u64) -> Self {
        self.block_compute_gas_limit = limit;
        self
    }

    /// Set a custom transaction state growth limit.
    ///
    /// This is a builder method that consumes self and returns a new instance
    /// with the specified transaction state growth limit.
    pub fn with_tx_state_growth_limit(mut self, limit: u64) -> Self {
        self.tx_state_growth_limit = limit;
        self
    }

    /// Set a custom block state growth limit.
    ///
    /// This is a builder method that consumes self and returns a new instance
    /// with the specified block state growth limit.
    pub fn with_block_state_growth_limit(mut self, limit: u64) -> Self {
        self.block_state_growth_limit = limit;
        self
    }

    /// Set a custom compute gas limit when accessing block environment data.
    ///
    /// This is a builder method that consumes self and returns a new instance
    /// with the specified block environment access compute gas limit.
    pub fn with_block_env_access_compute_gas_limit(mut self, limit: u64) -> Self {
        self.block_env_access_compute_gas_limit = limit;
        self
    }

    /// Set a custom compute gas limit when accessing oracle data.
    ///
    /// This is a builder method that consumes self and returns a new instance
    /// with the specified oracle access compute gas limit.
    pub fn with_oracle_access_compute_gas_limit(mut self, limit: u64) -> Self {
        self.oracle_access_compute_gas_limit = limit;
        self
    }

    /// Create a new block limiter from these limits.
    ///
    /// This converts the limit configuration into a stateful [`BlockLimiter`] that tracks
    /// resource usage and enforces the configured limits throughout block execution.
    ///
    /// # Returns
    ///
    /// A new [`BlockLimiter`] initialized with zero usage for all tracked resources.
    ///
    /// # Example
    ///
    /// ```rust,ignore
    /// let limits = BlockLimits::default().with_block_txs_data_limit(5_000);
    /// let limiter = limits.to_block_limiter();
    /// ```
    pub fn to_block_limiter(self) -> BlockLimiter {
        BlockLimiter {
            limits: self,
            block_gas_used: 0,
            block_data_used: 0,
            block_kv_updates_used: 0,
            block_tx_size_used: 0,
            block_da_size_used: 0,
            block_compute_gas_used: 0,
            block_state_growth_used: 0,
        }
    }

    /// Convert the block limits to the runtime limits for a single transaction.
    pub fn to_evm_tx_runtime_limits(&self) -> EvmTxRuntimeLimits {
        EvmTxRuntimeLimits {
            tx_data_size_limit: self.tx_data_limit,
            tx_kv_updates_limit: self.tx_kv_update_limit,
            tx_compute_gas_limit: self.tx_compute_gas_limit,
            tx_state_growth_limit: self.tx_state_growth_limit,
            block_env_access_compute_gas_limit: self.block_env_access_compute_gas_limit,
            oracle_access_compute_gas_limit: self.oracle_access_compute_gas_limit,
        }
    }
}

/// Stateful block resource limiter that tracks usage and enforces limits.
///
/// This struct maintains cumulative resource usage throughout block execution and validates
/// that each transaction stays within both transaction-level and block-level limits. It
/// provides a two-phase checking mechanism:
///
/// 1. **Pre-execution**: Validates limits that can be determined before execution (gas limit,
///    transaction size, DA size)
/// 2. **Post-execution**: Validates limits based on execution results (data size, KV updates) and
///    updates the usage accumulators
///
/// # Resource Tracking
///
/// The limiter tracks five cumulative metrics:
/// - Gas consumed by all transactions
/// - Total transaction body size
/// - Total data availability size
/// - Total execution data generated
/// - Total key-value storage updates
///
/// # Usage Pattern
///
/// ```rust,ignore
/// let mut limiter = BlockLimits::default().to_block_limiter();
///
/// for tx in transactions {
///     // Pre-execution check
///     limiter.pre_execution_check(tx.hash(), tx.gas_limit(), tx.size(), tx.da_size(), is_deposit)?;
///
///     let outcome = execute_transaction(tx);
///
///     // Post-execution update
///     limiter.post_execution_update(&outcome)?;
/// }
/// ```
#[derive(Debug, Clone)]
pub struct BlockLimiter {
    /// The configured resource limits.
    pub limits: BlockLimits,

    /// Cumulative gas consumed by all committed transactions in the block.
    pub block_gas_used: u64,

    /// Cumulative encoded size of all transaction bodies in the block (uncompressed).
    pub block_tx_size_used: u64,

    /// Cumulative data availability size for all transactions in the block (compressed).
    pub block_da_size_used: u64,

    /// Cumulative execution data generated by all transactions in the block.
    ///
    /// This includes the encoded transaction object, logs, return data, and other execution
    /// artifacts.
    pub block_data_used: u64,

    /// Cumulative key-value storage updates performed by all transactions in the block.
    ///
    /// This tracks the total number of SSTORE operations across all transactions.
    pub block_kv_updates_used: u64,

    /// Cumulative compute gas consumed by all transactions in the block.
    pub block_compute_gas_used: u64,

    /// Cumulative state growth consumed by all transactions in the block.
    pub block_state_growth_used: u64,
}

impl BlockLimiter {
    /// Create a new block limiter with the specified limits.
    ///
    /// Initializes a limiter with all resource usage counters set to zero.
    ///
    /// # Parameters
    ///
    /// - `limits`: The resource limit configuration
    ///
    /// # Returns
    ///
    /// A new limiter ready to track resource usage
    pub fn new(limits: BlockLimits) -> Self {
        Self {
            limits,
            block_gas_used: 0,
            block_data_used: 0,
            block_kv_updates_used: 0,
            block_tx_size_used: 0,
            block_da_size_used: 0,
            block_compute_gas_used: 0,
            block_state_growth_used: 0,
        }
    }

    /// Validate transaction against pre-execution limits.
    ///
    /// This method validates that a transaction can be included in the block by checking
    /// limits that are known before execution:
    /// - Single transaction gas limit
    /// - Remaining block gas capacity
    /// - Single transaction size limit
    /// - Remaining block transaction size capacity
    /// - Single transaction DA size limit
    /// - Remaining block DA size capacity
    ///
    /// **Important**: This method does **not** modify any state. It only performs validation.
    /// Call [`post_execution_update`](Self::post_execution_update) after execution to update
    /// usage counters.
    ///
    /// # Parameters
    ///
    /// - `tx_hash`: Transaction hash for error reporting
    /// - `gas_limit`: Transaction's declared gas limit
    /// - `tx_size`: Transaction's encoded size in bytes (EIP-2718 encoding)
    /// - `da_size`: Transaction's compressed data availability size in bytes
    /// - `is_deposit`: Whether the transaction is an L1-to-L2 deposit (exempt from DA size limits)
    ///
    /// # Returns
    ///
    /// - `Ok(())`: Transaction passes all pre-execution checks
    /// - `Err(BlockExecutionError)`: Transaction violates one or more limits
    ///
    /// # Errors
    ///
    /// Returns [`BlockExecutionError::Validation`] containing either:
    /// - [`MegaTxLimitExceededError`]: Transaction exceeds its own limits (invalid transaction)
    /// - [`MegaBlockLimitExceededError`]: Transaction would exceed block capacity
    /// - [`BlockValidationError::TransactionGasLimitMoreThanAvailableBlockGas`][] - Insufficient
    ///   remaining gas in block
    ///
    /// # Example
    ///
    /// ```rust,ignore
    /// let mut limiter = BlockLimits::default().to_block_limiter();
    ///
    /// limiter.pre_execution_check(
    ///     tx.hash(),
    ///     tx.gas_limit(),
    ///     tx.encode_2718_len() as u64,
    ///     tx.estimated_da_size(),
    ///     tx.is_deposit(),
    /// )?;
    /// ```
    pub fn pre_execution_check(
        &self,
        tx_hash: TxHash,
        gas_limit: u64,
        tx_size: u64,
        da_size: u64,
        is_deposit: bool,
    ) -> Result<(), BlockExecutionError> {
        // Check single transaction gas limit
        if gas_limit > self.limits.tx_gas_limit {
            return Err(BlockExecutionError::Validation(BlockValidationError::InvalidTx {
                hash: tx_hash,
                error: Box::new(MegaTxLimitExceededError::TransactionGasLimit {
                    tx_gas_limit: gas_limit,
                    limit: self.limits.tx_gas_limit,
                }),
            }));
        }

        // Check block gas limit
        if self.block_gas_used.saturating_add(gas_limit) > self.limits.block_gas_limit {
            return Err(BlockExecutionError::Validation(
                BlockValidationError::TransactionGasLimitMoreThanAvailableBlockGas {
                    transaction_gas_limit: gas_limit,
                    block_available_gas: self
                        .limits
                        .block_gas_limit
                        .saturating_sub(self.block_gas_used),
                },
            ));
        }

        // Check single transaction size limit
        if tx_size > self.limits.tx_encode_size_limit {
            return Err(BlockExecutionError::Validation(BlockValidationError::InvalidTx {
                hash: tx_hash,
                error: Box::new(MegaTxLimitExceededError::TransactionEncodeSizeLimit {
                    tx_size,
                    limit: self.limits.tx_encode_size_limit,
                }),
            }));
        }

        // Check block transaction size limit
        if tx_size.saturating_add(self.block_tx_size_used) > self.limits.block_txs_encode_size_limit
        {
            return Err(BlockExecutionError::Validation(BlockValidationError::InvalidTx {
                hash: tx_hash,
                error: Box::new(MegaBlockLimitExceededError::TransactionEncodeSizeLimit {
                    block_used: self.block_tx_size_used,
                    tx_used: tx_size,
                    limit: self.limits.block_txs_encode_size_limit,
                }),
            }));
        }

        // Deposit transactions are exempt from data availability size limits
        if !is_deposit {
            // Check single transaction data availability size limit
            if da_size > self.limits.tx_da_size_limit {
                return Err(BlockExecutionError::Validation(BlockValidationError::InvalidTx {
                    hash: tx_hash,
                    error: Box::new(MegaTxLimitExceededError::DataAvailabilitySizeLimit {
                        da_size,
                        limit: self.limits.tx_da_size_limit,
                    }),
                }));
            }

            // Check block data availability size limit
            if da_size.saturating_add(self.block_da_size_used) > self.limits.block_da_size_limit {
                return Err(BlockExecutionError::Validation(BlockValidationError::InvalidTx {
                    hash: tx_hash,
                    error: Box::new(MegaBlockLimitExceededError::DataAvailabilitySizeLimit {
                        block_used: self.block_da_size_used,
                        tx_used: da_size,
                        limit: self.limits.block_da_size_limit,
                    }),
                }));
            }
        }

        // Check block-level data limit
        if self.block_data_used >= self.limits.block_txs_data_limit {
            return Err(BlockExecutionError::Validation(BlockValidationError::InvalidTx {
                hash: tx_hash,
                error: Box::new(MegaBlockLimitExceededError::TransactionDataLimit {
                    block_used: self.block_data_used,
                    limit: self.limits.block_txs_data_limit,
                }),
            }));
        }

        // Check block-level kv update limit
        if self.block_kv_updates_used >= self.limits.block_kv_update_limit {
            return Err(BlockExecutionError::Validation(BlockValidationError::InvalidTx {
                hash: tx_hash,
                error: Box::new(MegaBlockLimitExceededError::KVUpdateLimit {
                    block_used: self.block_kv_updates_used,
                    limit: self.limits.block_kv_update_limit,
                }),
            }));
        }

        // Check block-level compute gas limit
        if self.block_compute_gas_used >= self.limits.block_compute_gas_limit {
            return Err(BlockExecutionError::Validation(BlockValidationError::InvalidTx {
                hash: tx_hash,
                error: Box::new(MegaBlockLimitExceededError::ComputeGasLimit {
                    block_used: self.block_compute_gas_used,
                    limit: self.limits.block_compute_gas_limit,
                }),
            }));
        }

        // Check block-level state growth limit
        if self.block_state_growth_used >= self.limits.block_state_growth_limit {
            return Err(BlockExecutionError::Validation(BlockValidationError::InvalidTx {
                hash: tx_hash,
                error: Box::new(MegaBlockLimitExceededError::StateGrowthLimit {
                    block_used: self.block_state_growth_used,
                    limit: self.limits.block_state_growth_limit,
                }),
            }));
        }

        Ok(())
    }

    /// Update usage counters after transaction execution.
    ///
    /// This method is called **after** transaction execution to accumulate the executed
    /// transaction's resource usage into the limiter's block-level counters. It does **not**
    /// validate post-execution limits — over-limit enforcement happens in
    /// [`pre_execution_check`](Self::pre_execution_check) before admitting the next transaction.
    /// The transaction may cause the block to exceed limits, which is intentional to maximize
    /// block utilization.
    ///
    /// The return type remains `Result` to leave room for future fallible post-execution logic;
    /// the current implementation always returns `Ok(())`.
    ///
    /// # Parameters
    ///
    /// - `outcome`: The transaction execution outcome containing resource usage information
    ///
    /// # Returns
    ///
    /// - `Ok(())`: Usage counters updated successfully
    ///
    /// # State Modification
    ///
    /// This method updates all cumulative usage counters:
    /// - `block_gas_used += gas_used`
    /// - `block_tx_size_used += tx_size_used`
    /// - `block_da_size_used += da_size_used` (only for non-deposit transactions)
    /// - `block_data_used += data_size_used`
    /// - `block_kv_updates_used += kv_updates_used`
    /// - `block_compute_gas_used += compute_gas_used`
    /// - `block_state_growth_used += state_growth_used`
    ///
    /// **Note**: The block may exceed limits after this update. This is intentional - the first
    /// transaction that causes the block to exceed is allowed to be included.
    ///
    /// # Example
    ///
    /// ```rust,ignore
    /// let outcome = executor.execute_mega_transaction(tx)?;
    ///
    /// // Accumulates usage; may cause block-level counters to exceed limits.
    /// limiter.post_execution_update(&outcome)?;
    ///
    /// // Commit the transaction state
    /// executor.commit_execution_outcome(outcome)?;
    /// ```
    pub fn post_execution_update<T: Transaction + MegaTransactionExt>(
        &mut self,
        outcome: &BlockMegaTransactionOutcome<impl RecoveredTx<T>>,
    ) -> Result<(), BlockExecutionError> {
        let is_deposit = outcome.tx.tx().ty() == DEPOSIT_TRANSACTION_TYPE;

        self.post_execution_update_raw(
            outcome.result.gas_used(),
            outcome.tx_size,
            outcome.da_size,
            outcome.data_size,
            outcome.kv_updates,
            outcome.compute_gas_used,
            outcome.state_growth_used,
            is_deposit,
        );

        Ok(())
    }

    /// Update usage counters after transaction execution using raw values.
    ///
    /// This mirrors [`post_execution_update`](Self::post_execution_update) but takes precomputed
    /// resource usage values instead of a full execution outcome.
    #[allow(clippy::too_many_arguments)]
    pub fn post_execution_update_raw(
        &mut self,
        gas_used: u64,
        tx_size: u64,
        da_size: u64,
        tx_data: u64,
        kv_updates: u64,
        compute_gas_used: u64,
        state_growth_used: u64,
        is_deposit: bool,
    ) {
        // Block gas limit. No need to check here since it's checked before transaction execution.
        self.block_gas_used = self.block_gas_used.saturating_add(gas_used);

        // Block tx size limit, no need to check here since it's checked before transaction
        // execution.
        self.block_tx_size_used = self.block_tx_size_used.saturating_add(tx_size);

        // Block da size limit, no need to check here since it's checked before transaction
        // execution. Only appliable for non-deposit transactions.
        if !is_deposit {
            self.block_da_size_used = self.block_da_size_used.saturating_add(da_size);
        }

        // Block data limit, no need to check here since we allow the last transaction to exceed the
        // limit.
        self.block_data_used = self.block_data_used.saturating_add(tx_data);

        // Block kv updates limit, no need to check here since we allow the last transaction to
        // exceed the limit.
        self.block_kv_updates_used = self.block_kv_updates_used.saturating_add(kv_updates);

        // Block compute gas limit, no need to check here since we allow the last transaction to
        // exceed the limit.
        self.block_compute_gas_used = self.block_compute_gas_used.saturating_add(compute_gas_used);

        // Block state growth limit, no need to check here since we allow the last transaction to
        // exceed the limit.
        self.block_state_growth_used =
            self.block_state_growth_used.saturating_add(state_growth_used);
    }

    /// Returns true if any block-level limit has been reached or exceeded.
    pub fn is_block_limit_reached(&self) -> bool {
        self.block_gas_used >= self.limits.block_gas_limit ||
            self.block_tx_size_used >= self.limits.block_txs_encode_size_limit ||
            self.block_da_size_used >= self.limits.block_da_size_limit ||
            self.block_data_used >= self.limits.block_txs_data_limit ||
            self.block_kv_updates_used >= self.limits.block_kv_update_limit ||
            self.block_compute_gas_used >= self.limits.block_compute_gas_limit ||
            self.block_state_growth_used >= self.limits.block_state_growth_limit
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use alloy_primitives::B256;

    fn limits_with_block_gas(block_gas_limit: u64) -> BlockLimits {
        let mut limits = BlockLimits::no_limits();
        limits.block_gas_limit = block_gas_limit;
        limits.tx_gas_limit = u64::MAX;
        limits
    }

    fn limits_with_block_tx_size(block_txs_encode_size_limit: u64) -> BlockLimits {
        let mut limits = BlockLimits::no_limits();
        limits.block_txs_encode_size_limit = block_txs_encode_size_limit;
        limits
    }

    fn limits_with_block_da_size(block_da_size_limit: u64) -> BlockLimits {
        let mut limits = BlockLimits::no_limits();
        limits.block_da_size_limit = block_da_size_limit;
        limits
    }

    #[test]
    fn test_pre_execution_check_block_gas_addition_saturates() {
        // Block has very high accumulated usage and a transaction with a near-`u64::MAX`
        // gas limit; unchecked addition would wrap and accidentally pass the limit check.
        let mut limiter = BlockLimiter::new(limits_with_block_gas(1_000_000));
        limiter.block_gas_used = u64::MAX - 10;
        let result = limiter.pre_execution_check(B256::ZERO, u64::MAX, 0, 0, false);
        assert!(result.is_err(), "saturating_add must keep the rejection in place");
    }

    #[test]
    fn test_pre_execution_check_block_tx_size_addition_saturates() {
        let mut limiter = BlockLimiter::new(limits_with_block_tx_size(1_000_000));
        limiter.block_tx_size_used = u64::MAX - 10;
        let result = limiter.pre_execution_check(B256::ZERO, 0, u64::MAX, 0, false);
        assert!(result.is_err());
    }

    #[test]
    fn test_pre_execution_check_block_da_size_addition_saturates() {
        let mut limiter = BlockLimiter::new(limits_with_block_da_size(1_000_000));
        limiter.block_da_size_used = u64::MAX - 10;
        let result = limiter.pre_execution_check(B256::ZERO, 0, 0, u64::MAX, false);
        assert!(result.is_err());
    }

    #[test]
    fn test_post_execution_update_raw_saturates_all_counters() {
        let mut limiter = BlockLimiter::new(BlockLimits::no_limits());
        limiter.block_gas_used = u64::MAX - 1;
        limiter.block_tx_size_used = u64::MAX - 1;
        limiter.block_da_size_used = u64::MAX - 1;
        limiter.block_data_used = u64::MAX - 1;
        limiter.block_kv_updates_used = u64::MAX - 1;
        limiter.block_compute_gas_used = u64::MAX - 1;
        limiter.block_state_growth_used = u64::MAX - 1;

        limiter.post_execution_update_raw(
            u64::MAX,
            u64::MAX,
            u64::MAX,
            u64::MAX,
            u64::MAX,
            u64::MAX,
            u64::MAX,
            false,
        );

        assert_eq!(limiter.block_gas_used, u64::MAX);
        assert_eq!(limiter.block_tx_size_used, u64::MAX);
        assert_eq!(limiter.block_da_size_used, u64::MAX);
        assert_eq!(limiter.block_data_used, u64::MAX);
        assert_eq!(limiter.block_kv_updates_used, u64::MAX);
        assert_eq!(limiter.block_compute_gas_used, u64::MAX);
        assert_eq!(limiter.block_state_growth_used, u64::MAX);
    }

    #[test]
    fn test_post_execution_update_raw_skips_da_for_deposits() {
        // Deposit transactions should not advance `block_da_size_used`, even when the value
        // would otherwise saturate.
        let mut limiter = BlockLimiter::new(BlockLimits::no_limits());
        limiter.block_da_size_used = 100;

        limiter.post_execution_update_raw(0, 0, u64::MAX, 0, 0, 0, 0, true);

        assert_eq!(limiter.block_da_size_used, 100);
    }
}