1use crate::{
4 AccountReader, BlockBodyIndicesProvider, BlockHashReader, BlockIdReader, BlockNumReader,
5 BlockReader, BlockReaderIdExt, BlockSource, BytecodeReader, ChangeSetReader,
6 HashedPostStateProvider, HeaderProvider, NodePrimitivesProvider, PruneCheckpointReader,
7 ReceiptProvider, ReceiptProviderIdExt, StageCheckpointReader, StateProofProvider,
8 StateProvider, StateProviderBox, StateProviderFactory, StateReader, StateRootProvider,
9 StorageRootProvider, TransactionVariant, TransactionsProvider,
10};
11
12#[cfg(feature = "db-api")]
13use crate::{DBProvider, DatabaseProviderFactory, StorageChangeSetReader, StorageSettingsCache};
14use alloc::{boxed::Box, string::String, sync::Arc, vec::Vec};
15use alloy_consensus::transaction::TransactionMeta;
16use alloy_eips::{BlockHashOrNumber, BlockId, BlockNumberOrTag};
17use alloy_primitives::{
18 Address, BlockHash, BlockNumber, Bytes, StorageKey, StorageValue, TxHash, TxNumber, B256,
19};
20use core::{
21 fmt::Debug,
22 marker::PhantomData,
23 ops::{RangeBounds, RangeInclusive},
24};
25use reth_chainspec::{ChainInfo, ChainSpecProvider, EthChainSpec, MAINNET};
26#[cfg(feature = "db-api")]
27use reth_db_api::mock::{DatabaseMock, TxMock};
28use reth_db_models::{AccountBeforeTx, StoredBlockBodyIndices};
29use reth_ethereum_primitives::EthPrimitives;
30use reth_execution_types::ExecutionOutcome;
31use reth_primitives_traits::{Account, Bytecode, NodePrimitives, RecoveredBlock, SealedHeader};
32#[cfg(feature = "db-api")]
33use reth_prune_types::PruneModes;
34use reth_prune_types::{PruneCheckpoint, PruneSegment};
35use reth_stages_types::{StageCheckpoint, StageId};
36use reth_storage_errors::provider::{ProviderError, ProviderResult};
37use reth_trie_common::{
38 updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof,
39 MultiProofTargets, StorageMultiProof, StorageProof, TrieInput,
40};
41
42#[derive(Debug)]
44#[non_exhaustive]
45pub struct NoopProvider<ChainSpec = reth_chainspec::ChainSpec, N = EthPrimitives> {
46 chain_spec: Arc<ChainSpec>,
47 #[cfg(feature = "db-api")]
48 tx: TxMock,
49 #[cfg(feature = "db-api")]
50 prune_modes: PruneModes,
51 _phantom: PhantomData<N>,
52}
53
54impl<ChainSpec, N> NoopProvider<ChainSpec, N> {
55 pub fn new(chain_spec: Arc<ChainSpec>) -> Self {
57 Self {
58 chain_spec,
59 #[cfg(feature = "db-api")]
60 tx: TxMock::default(),
61 #[cfg(feature = "db-api")]
62 prune_modes: PruneModes::default(),
63 _phantom: Default::default(),
64 }
65 }
66}
67
68impl<ChainSpec> NoopProvider<ChainSpec> {
69 pub fn eth(chain_spec: Arc<ChainSpec>) -> Self {
71 Self {
72 chain_spec,
73 #[cfg(feature = "db-api")]
74 tx: TxMock::default(),
75 #[cfg(feature = "db-api")]
76 prune_modes: PruneModes::default(),
77 _phantom: Default::default(),
78 }
79 }
80}
81
82impl NoopProvider {
83 pub fn mainnet() -> Self {
85 Self::eth(MAINNET.clone())
86 }
87}
88
89impl Default for NoopProvider {
90 fn default() -> Self {
91 Self::mainnet()
92 }
93}
94
95impl<ChainSpec, N> Clone for NoopProvider<ChainSpec, N> {
96 fn clone(&self) -> Self {
97 Self {
98 chain_spec: Arc::clone(&self.chain_spec),
99 #[cfg(feature = "db-api")]
100 tx: self.tx.clone(),
101 #[cfg(feature = "db-api")]
102 prune_modes: self.prune_modes.clone(),
103 _phantom: Default::default(),
104 }
105 }
106}
107
108impl<ChainSpec: Send + Sync, N: Send + Sync> BlockHashReader for NoopProvider<ChainSpec, N> {
110 fn block_hash(&self, _number: u64) -> ProviderResult<Option<B256>> {
111 Ok(None)
112 }
113
114 fn canonical_hashes_range(
115 &self,
116 _start: BlockNumber,
117 _end: BlockNumber,
118 ) -> ProviderResult<Vec<B256>> {
119 Ok(Vec::new())
120 }
121}
122
123impl<ChainSpec: Send + Sync, N: Send + Sync> BlockNumReader for NoopProvider<ChainSpec, N> {
124 fn chain_info(&self) -> ProviderResult<ChainInfo> {
125 Ok(ChainInfo::default())
126 }
127
128 fn best_block_number(&self) -> ProviderResult<BlockNumber> {
129 Ok(0)
130 }
131
132 fn last_block_number(&self) -> ProviderResult<BlockNumber> {
133 Ok(0)
134 }
135
136 fn block_number(&self, _hash: B256) -> ProviderResult<Option<BlockNumber>> {
137 Ok(None)
138 }
139}
140
141impl<ChainSpec: EthChainSpec + 'static, N: Debug + Send + Sync + 'static> ChainSpecProvider
142 for NoopProvider<ChainSpec, N>
143{
144 type ChainSpec = ChainSpec;
145
146 fn chain_spec(&self) -> Arc<Self::ChainSpec> {
147 self.chain_spec.clone()
148 }
149}
150
151impl<C: Send + Sync, N: NodePrimitives> BlockIdReader for NoopProvider<C, N> {
152 fn pending_block_num_hash(&self) -> ProviderResult<Option<alloy_eips::BlockNumHash>> {
153 Ok(None)
154 }
155
156 fn safe_block_num_hash(&self) -> ProviderResult<Option<alloy_eips::BlockNumHash>> {
157 Ok(None)
158 }
159
160 fn finalized_block_num_hash(&self) -> ProviderResult<Option<alloy_eips::BlockNumHash>> {
161 Ok(None)
162 }
163}
164
165impl<C: Send + Sync, N: NodePrimitives> BlockReaderIdExt for NoopProvider<C, N> {
166 fn block_by_id(&self, _id: BlockId) -> ProviderResult<Option<N::Block>> {
167 Ok(None)
168 }
169
170 fn sealed_header_by_id(
171 &self,
172 _id: BlockId,
173 ) -> ProviderResult<Option<SealedHeader<N::BlockHeader>>> {
174 Ok(None)
175 }
176
177 fn header_by_id(&self, _id: BlockId) -> ProviderResult<Option<N::BlockHeader>> {
178 Ok(None)
179 }
180}
181
182impl<C: Send + Sync, N: NodePrimitives> BlockReader for NoopProvider<C, N> {
183 type Block = N::Block;
184
185 fn find_block_by_hash(
186 &self,
187 _hash: B256,
188 _source: BlockSource,
189 ) -> ProviderResult<Option<Self::Block>> {
190 Ok(None)
191 }
192
193 fn block(&self, _id: BlockHashOrNumber) -> ProviderResult<Option<Self::Block>> {
194 Ok(None)
195 }
196
197 fn pending_block(&self) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
198 Ok(None)
199 }
200
201 fn pending_block_and_receipts(
202 &self,
203 ) -> ProviderResult<Option<(RecoveredBlock<Self::Block>, Vec<Self::Receipt>)>> {
204 Ok(None)
205 }
206
207 fn recovered_block(
208 &self,
209 _id: BlockHashOrNumber,
210 _transaction_kind: TransactionVariant,
211 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
212 Ok(None)
213 }
214
215 fn sealed_block_with_senders(
216 &self,
217 _id: BlockHashOrNumber,
218 _transaction_kind: TransactionVariant,
219 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
220 Ok(None)
221 }
222
223 fn block_range(&self, _range: RangeInclusive<BlockNumber>) -> ProviderResult<Vec<Self::Block>> {
224 Ok(Vec::new())
225 }
226
227 fn block_with_senders_range(
228 &self,
229 _range: RangeInclusive<BlockNumber>,
230 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>> {
231 Ok(Vec::new())
232 }
233
234 fn recovered_block_range(
235 &self,
236 _range: RangeInclusive<BlockNumber>,
237 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>> {
238 Ok(Vec::new())
239 }
240
241 fn block_by_transaction_id(&self, _id: TxNumber) -> ProviderResult<Option<BlockNumber>> {
242 Ok(None)
243 }
244}
245
246impl<C: Send + Sync, N: NodePrimitives> TransactionsProvider for NoopProvider<C, N> {
247 type Transaction = N::SignedTx;
248
249 fn transaction_id(&self, _tx_hash: TxHash) -> ProviderResult<Option<TxNumber>> {
250 Ok(None)
251 }
252
253 fn transaction_by_id(&self, _id: TxNumber) -> ProviderResult<Option<Self::Transaction>> {
254 Ok(None)
255 }
256
257 fn transaction_by_id_unhashed(
258 &self,
259 _id: TxNumber,
260 ) -> ProviderResult<Option<Self::Transaction>> {
261 Ok(None)
262 }
263
264 fn transaction_by_hash(&self, _hash: TxHash) -> ProviderResult<Option<Self::Transaction>> {
265 Ok(None)
266 }
267
268 fn transaction_by_hash_with_meta(
269 &self,
270 _hash: TxHash,
271 ) -> ProviderResult<Option<(Self::Transaction, TransactionMeta)>> {
272 Ok(None)
273 }
274
275 fn transactions_by_block(
276 &self,
277 _block_id: BlockHashOrNumber,
278 ) -> ProviderResult<Option<Vec<Self::Transaction>>> {
279 Ok(None)
280 }
281
282 fn transactions_by_block_range(
283 &self,
284 _range: impl RangeBounds<BlockNumber>,
285 ) -> ProviderResult<Vec<Vec<Self::Transaction>>> {
286 Ok(Vec::default())
287 }
288
289 fn transactions_by_tx_range(
290 &self,
291 _range: impl RangeBounds<TxNumber>,
292 ) -> ProviderResult<Vec<Self::Transaction>> {
293 Ok(Vec::default())
294 }
295
296 fn senders_by_tx_range(
297 &self,
298 _range: impl RangeBounds<TxNumber>,
299 ) -> ProviderResult<Vec<Address>> {
300 Ok(Vec::default())
301 }
302
303 fn transaction_sender(&self, _id: TxNumber) -> ProviderResult<Option<Address>> {
304 Ok(None)
305 }
306}
307
308impl<C: Send + Sync, N: NodePrimitives> ReceiptProvider for NoopProvider<C, N> {
309 type Receipt = N::Receipt;
310
311 fn receipt(&self, _id: TxNumber) -> ProviderResult<Option<Self::Receipt>> {
312 Ok(None)
313 }
314
315 fn receipt_by_hash(&self, _hash: TxHash) -> ProviderResult<Option<Self::Receipt>> {
316 Ok(None)
317 }
318
319 fn receipts_by_block(
320 &self,
321 _block: BlockHashOrNumber,
322 ) -> ProviderResult<Option<Vec<Self::Receipt>>> {
323 Ok(None)
324 }
325
326 fn receipts_by_tx_range(
327 &self,
328 _range: impl RangeBounds<TxNumber>,
329 ) -> ProviderResult<Vec<Self::Receipt>> {
330 Ok(Vec::new())
331 }
332
333 fn receipts_by_block_range(
334 &self,
335 _block_range: RangeInclusive<BlockNumber>,
336 ) -> ProviderResult<Vec<Vec<Self::Receipt>>> {
337 Ok(Vec::new())
338 }
339}
340
341impl<C: Send + Sync, N: NodePrimitives> ReceiptProviderIdExt for NoopProvider<C, N> {}
342
343impl<C: Send + Sync, N: NodePrimitives> HeaderProvider for NoopProvider<C, N> {
344 type Header = N::BlockHeader;
345
346 fn header(&self, _block_hash: BlockHash) -> ProviderResult<Option<Self::Header>> {
347 Ok(None)
348 }
349
350 fn header_by_number(&self, _num: u64) -> ProviderResult<Option<Self::Header>> {
351 Ok(None)
352 }
353
354 fn headers_range(
355 &self,
356 _range: impl RangeBounds<BlockNumber>,
357 ) -> ProviderResult<Vec<Self::Header>> {
358 Ok(Vec::new())
359 }
360
361 fn sealed_header(
362 &self,
363 _number: BlockNumber,
364 ) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
365 Ok(None)
366 }
367
368 fn sealed_headers_while(
369 &self,
370 _range: impl RangeBounds<BlockNumber>,
371 _predicate: impl FnMut(&SealedHeader<Self::Header>) -> bool,
372 ) -> ProviderResult<Vec<SealedHeader<Self::Header>>> {
373 Ok(Vec::new())
374 }
375}
376
377impl<C: Send + Sync, N: NodePrimitives> AccountReader for NoopProvider<C, N> {
378 fn basic_account(&self, _address: &Address) -> ProviderResult<Option<Account>> {
379 Ok(None)
380 }
381}
382
383impl<C: Send + Sync, N: NodePrimitives> ChangeSetReader for NoopProvider<C, N> {
384 fn account_block_changeset(
385 &self,
386 _block_number: BlockNumber,
387 ) -> ProviderResult<Vec<AccountBeforeTx>> {
388 Ok(Vec::default())
389 }
390
391 fn get_account_before_block(
392 &self,
393 _block_number: BlockNumber,
394 _address: Address,
395 ) -> ProviderResult<Option<AccountBeforeTx>> {
396 Ok(None)
397 }
398
399 fn account_changesets_range(
400 &self,
401 _range: impl core::ops::RangeBounds<BlockNumber>,
402 ) -> ProviderResult<Vec<(BlockNumber, AccountBeforeTx)>> {
403 Ok(Vec::default())
404 }
405
406 fn account_changeset_count(&self) -> ProviderResult<usize> {
407 Ok(0)
408 }
409}
410
411#[cfg(feature = "db-api")]
412impl<C: Send + Sync, N: NodePrimitives> StorageChangeSetReader for NoopProvider<C, N> {
413 fn storage_changeset(
414 &self,
415 _block_number: BlockNumber,
416 ) -> ProviderResult<
417 Vec<(reth_db_api::models::BlockNumberAddress, reth_primitives_traits::StorageEntry)>,
418 > {
419 Ok(Vec::default())
420 }
421
422 fn get_storage_before_block(
423 &self,
424 _block_number: BlockNumber,
425 _address: Address,
426 _storage_key: B256,
427 ) -> ProviderResult<Option<reth_primitives_traits::StorageEntry>> {
428 Ok(None)
429 }
430
431 fn storage_changesets_range(
432 &self,
433 _range: impl core::ops::RangeBounds<BlockNumber>,
434 ) -> ProviderResult<
435 Vec<(reth_db_api::models::BlockNumberAddress, reth_primitives_traits::StorageEntry)>,
436 > {
437 Ok(Vec::default())
438 }
439
440 fn storage_changeset_count(&self) -> ProviderResult<usize> {
441 Ok(0)
442 }
443}
444
445impl<C: Send + Sync, N: NodePrimitives> StateRootProvider for NoopProvider<C, N> {
446 fn state_root(&self, _state: HashedPostState) -> ProviderResult<B256> {
447 Ok(B256::default())
448 }
449
450 fn state_root_from_nodes(&self, _input: TrieInput) -> ProviderResult<B256> {
451 Ok(B256::default())
452 }
453
454 fn state_root_with_updates(
455 &self,
456 _state: HashedPostState,
457 ) -> ProviderResult<(B256, TrieUpdates)> {
458 Ok((B256::default(), TrieUpdates::default()))
459 }
460
461 fn state_root_from_nodes_with_updates(
462 &self,
463 _input: TrieInput,
464 ) -> ProviderResult<(B256, TrieUpdates)> {
465 Ok((B256::default(), TrieUpdates::default()))
466 }
467}
468
469impl<C: Send + Sync, N: NodePrimitives> StorageRootProvider for NoopProvider<C, N> {
470 fn storage_root(
471 &self,
472 _address: Address,
473 _hashed_storage: HashedStorage,
474 ) -> ProviderResult<B256> {
475 Ok(B256::default())
476 }
477
478 fn storage_proof(
479 &self,
480 _address: Address,
481 slot: B256,
482 _hashed_storage: HashedStorage,
483 ) -> ProviderResult<StorageProof> {
484 Ok(StorageProof::new(slot))
485 }
486
487 fn storage_multiproof(
488 &self,
489 _address: Address,
490 _slots: &[B256],
491 _hashed_storage: HashedStorage,
492 ) -> ProviderResult<StorageMultiProof> {
493 Ok(StorageMultiProof::empty())
494 }
495}
496
497impl<C: Send + Sync, N: NodePrimitives> StateProofProvider for NoopProvider<C, N> {
498 fn proof(
499 &self,
500 _input: TrieInput,
501 address: Address,
502 _slots: &[B256],
503 ) -> ProviderResult<AccountProof> {
504 Ok(AccountProof::new(address))
505 }
506
507 fn multiproof(
508 &self,
509 _input: TrieInput,
510 _targets: MultiProofTargets,
511 ) -> ProviderResult<MultiProof> {
512 Ok(MultiProof::default())
513 }
514
515 fn witness(&self, _input: TrieInput, _target: HashedPostState) -> ProviderResult<Vec<Bytes>> {
516 Ok(Vec::default())
517 }
518}
519
520impl<C: Send + Sync, N: NodePrimitives> HashedPostStateProvider for NoopProvider<C, N> {
521 fn hashed_post_state(&self, _bundle_state: &revm_database::BundleState) -> HashedPostState {
522 HashedPostState::default()
523 }
524}
525
526impl<C: Send + Sync, N: NodePrimitives> StateReader for NoopProvider<C, N> {
527 type Receipt = N::Receipt;
528
529 fn get_state(
530 &self,
531 _block: BlockNumber,
532 ) -> ProviderResult<Option<ExecutionOutcome<Self::Receipt>>> {
533 Ok(None)
534 }
535}
536
537impl<C: Send + Sync, N: NodePrimitives> StateProvider for NoopProvider<C, N> {
538 fn storage(
539 &self,
540 _account: Address,
541 _storage_key: StorageKey,
542 ) -> ProviderResult<Option<StorageValue>> {
543 Ok(None)
544 }
545}
546
547impl<C: Send + Sync, N: NodePrimitives> BytecodeReader for NoopProvider<C, N> {
548 fn bytecode_by_hash(&self, _code_hash: &B256) -> ProviderResult<Option<Bytecode>> {
549 Ok(None)
550 }
551}
552
553impl<C: Send + Sync + 'static, N: NodePrimitives> StateProviderFactory for NoopProvider<C, N> {
554 fn latest(&self) -> ProviderResult<StateProviderBox> {
555 Ok(Box::new(self.clone()))
556 }
557
558 fn state_by_block_number_or_tag(
559 &self,
560 number_or_tag: BlockNumberOrTag,
561 ) -> ProviderResult<StateProviderBox> {
562 match number_or_tag {
563 BlockNumberOrTag::Latest => self.latest(),
564 BlockNumberOrTag::Finalized => {
565 let hash =
567 self.finalized_block_hash()?.ok_or(ProviderError::FinalizedBlockNotFound)?;
568
569 self.history_by_block_hash(hash)
571 }
572 BlockNumberOrTag::Safe => {
573 let hash = self.safe_block_hash()?.ok_or(ProviderError::SafeBlockNotFound)?;
575
576 self.history_by_block_hash(hash)
577 }
578 BlockNumberOrTag::Earliest => {
579 self.history_by_block_number(self.earliest_block_number()?)
580 }
581 BlockNumberOrTag::Pending => self.pending(),
582 BlockNumberOrTag::Number(num) => self.history_by_block_number(num),
583 }
584 }
585
586 fn history_by_block_number(&self, _block: BlockNumber) -> ProviderResult<StateProviderBox> {
587 Ok(Box::new(self.clone()))
588 }
589
590 fn history_by_block_hash(&self, _block: BlockHash) -> ProviderResult<StateProviderBox> {
591 Ok(Box::new(self.clone()))
592 }
593
594 fn state_by_block_hash(&self, _block: BlockHash) -> ProviderResult<StateProviderBox> {
595 Ok(Box::new(self.clone()))
596 }
597
598 fn pending(&self) -> ProviderResult<StateProviderBox> {
599 Ok(Box::new(self.clone()))
600 }
601
602 fn pending_state_by_hash(&self, _block_hash: B256) -> ProviderResult<Option<StateProviderBox>> {
603 Ok(Some(Box::new(self.clone())))
604 }
605
606 fn maybe_pending(&self) -> ProviderResult<Option<StateProviderBox>> {
607 Ok(Some(Box::new(self.clone())))
608 }
609}
610
611impl<C: Send + Sync, N: NodePrimitives> StageCheckpointReader for NoopProvider<C, N> {
612 fn get_stage_checkpoint(&self, _id: StageId) -> ProviderResult<Option<StageCheckpoint>> {
613 Ok(None)
614 }
615
616 fn get_stage_checkpoint_progress(&self, _id: StageId) -> ProviderResult<Option<Vec<u8>>> {
617 Ok(None)
618 }
619
620 fn get_all_checkpoints(&self) -> ProviderResult<Vec<(String, StageCheckpoint)>> {
621 Ok(Vec::new())
622 }
623}
624
625impl<C: Send + Sync, N: NodePrimitives> PruneCheckpointReader for NoopProvider<C, N> {
626 fn get_prune_checkpoint(
627 &self,
628 _segment: PruneSegment,
629 ) -> ProviderResult<Option<PruneCheckpoint>> {
630 Ok(None)
631 }
632
633 fn get_prune_checkpoints(&self) -> ProviderResult<Vec<(PruneSegment, PruneCheckpoint)>> {
634 Ok(Vec::new())
635 }
636}
637
638impl<C: Send + Sync, N: NodePrimitives> NodePrimitivesProvider for NoopProvider<C, N> {
639 type Primitives = N;
640}
641
642impl<C: Send + Sync, N: Send + Sync> BlockBodyIndicesProvider for NoopProvider<C, N> {
643 fn block_body_indices(&self, _num: u64) -> ProviderResult<Option<StoredBlockBodyIndices>> {
644 Ok(None)
645 }
646
647 fn block_body_indices_range(
648 &self,
649 _range: RangeInclusive<BlockNumber>,
650 ) -> ProviderResult<Vec<StoredBlockBodyIndices>> {
651 Ok(Vec::new())
652 }
653}
654
655#[cfg(feature = "db-api")]
656impl<ChainSpec: Send + Sync, N: NodePrimitives> DBProvider for NoopProvider<ChainSpec, N> {
657 type Tx = TxMock;
658
659 fn tx_ref(&self) -> &Self::Tx {
660 &self.tx
661 }
662
663 fn tx_mut(&mut self) -> &mut Self::Tx {
664 &mut self.tx
665 }
666
667 fn into_tx(self) -> Self::Tx {
668 self.tx
669 }
670
671 fn prune_modes_ref(&self) -> &PruneModes {
672 &self.prune_modes
673 }
674
675 fn commit(self) -> ProviderResult<()> {
676 use reth_db_api::transaction::DbTx;
677
678 Ok(self.tx.commit()?)
679 }
680}
681
682#[cfg(feature = "db-api")]
683impl<ChainSpec: Send + Sync, N: NodePrimitives> DatabaseProviderFactory
684 for NoopProvider<ChainSpec, N>
685{
686 type DB = DatabaseMock;
687 type Provider = Self;
688 type ProviderRW = Self;
689
690 fn database_provider_ro(&self) -> ProviderResult<Self::Provider> {
691 Ok(self.clone())
692 }
693
694 fn database_provider_rw(&self) -> ProviderResult<Self::ProviderRW> {
695 Ok(self.clone())
696 }
697}
698
699#[cfg(feature = "db-api")]
700impl<ChainSpec: Send + Sync, N: Send + Sync> StorageSettingsCache for NoopProvider<ChainSpec, N> {
701 fn cached_storage_settings(&self) -> reth_db_api::models::StorageSettings {
702 reth_db_api::models::StorageSettings::default()
703 }
704
705 fn set_storage_settings_cache(&self, _settings: reth_db_api::models::StorageSettings) {}
706}