1#![warn(unused_crate_dependencies)]
20
21pub mod overrides;
22
23use std::sync::Arc;
24
25use ethereum::{BlockV3, ReceiptV4};
26use ethereum_types::{Address, H256, U256};
27use sc_client_api::{backend::Backend, StorageProvider};
29use sp_api::ProvideRuntimeApi;
30use sp_runtime::{traits::Block as BlockT, Permill};
31use fp_rpc::{EthereumRuntimeRPCApi, TransactionStatus};
33use fp_storage::EthereumStorageSchema;
34
35pub use self::overrides::*;
36
37#[derive(Clone)]
45pub struct StorageOverrideHandler<B, C, BE> {
46 querier: StorageQuerier<B, C, BE>,
47 fallback: RuntimeApiStorageOverride<B, C>,
48}
49
50impl<B, C, BE> StorageOverrideHandler<B, C, BE> {
51 pub fn new(client: Arc<C>) -> Self {
52 Self {
53 querier: StorageQuerier::new(client.clone()),
54 fallback: RuntimeApiStorageOverride::<B, C>::new(client),
55 }
56 }
57}
58
59impl<B, C, BE> StorageOverride<B> for StorageOverrideHandler<B, C, BE>
60where
61 B: BlockT,
62 C: ProvideRuntimeApi<B>,
63 C::Api: EthereumRuntimeRPCApi<B>,
64 C: StorageProvider<B, BE> + Send + Sync + 'static,
65 BE: Backend<B> + 'static,
66{
67 fn account_code_at(&self, at: B::Hash, address: Address) -> Option<Vec<u8>> {
68 match self.querier.storage_schema(at) {
69 Some(EthereumStorageSchema::V1) => {
70 SchemaV1StorageOverrideRef::new(&self.querier).account_code_at(at, address)
71 }
72 Some(EthereumStorageSchema::V2) => {
73 SchemaV2StorageOverrideRef::new(&self.querier).account_code_at(at, address)
74 }
75 Some(EthereumStorageSchema::V3) => {
76 SchemaV3StorageOverrideRef::new(&self.querier).account_code_at(at, address)
77 }
78 None => self.fallback.account_code_at(at, address),
79 }
80 }
81
82 fn account_storage_at(&self, at: B::Hash, address: Address, index: U256) -> Option<H256> {
83 match self.querier.storage_schema(at) {
84 Some(EthereumStorageSchema::V1) => SchemaV1StorageOverrideRef::new(&self.querier)
85 .account_storage_at(at, address, index),
86 Some(EthereumStorageSchema::V2) => SchemaV2StorageOverrideRef::new(&self.querier)
87 .account_storage_at(at, address, index),
88 Some(EthereumStorageSchema::V3) => SchemaV3StorageOverrideRef::new(&self.querier)
89 .account_storage_at(at, address, index),
90 None => self.fallback.account_storage_at(at, address, index),
91 }
92 }
93
94 fn current_block(&self, at: B::Hash) -> Option<BlockV3> {
95 match self.querier.storage_schema(at) {
96 Some(EthereumStorageSchema::V1) => {
97 SchemaV1StorageOverrideRef::new(&self.querier).current_block(at)
98 }
99 Some(EthereumStorageSchema::V2) => {
100 SchemaV2StorageOverrideRef::new(&self.querier).current_block(at)
101 }
102 Some(EthereumStorageSchema::V3) => {
103 SchemaV3StorageOverrideRef::new(&self.querier).current_block(at)
104 }
105 None => self.fallback.current_block(at),
106 }
107 }
108
109 fn current_receipts(&self, at: B::Hash) -> Option<Vec<ReceiptV4>> {
110 match self.querier.storage_schema(at) {
111 Some(EthereumStorageSchema::V1) => {
112 SchemaV1StorageOverrideRef::new(&self.querier).current_receipts(at)
113 }
114 Some(EthereumStorageSchema::V2) => {
115 SchemaV2StorageOverrideRef::new(&self.querier).current_receipts(at)
116 }
117 Some(EthereumStorageSchema::V3) => {
118 SchemaV3StorageOverrideRef::new(&self.querier).current_receipts(at)
119 }
120 None => self.fallback.current_receipts(at),
121 }
122 }
123
124 fn current_transaction_statuses(&self, at: B::Hash) -> Option<Vec<TransactionStatus>> {
125 match self.querier.storage_schema(at) {
126 Some(EthereumStorageSchema::V1) => {
127 SchemaV1StorageOverrideRef::new(&self.querier).current_transaction_statuses(at)
128 }
129 Some(EthereumStorageSchema::V2) => {
130 SchemaV2StorageOverrideRef::new(&self.querier).current_transaction_statuses(at)
131 }
132 Some(EthereumStorageSchema::V3) => {
133 SchemaV3StorageOverrideRef::new(&self.querier).current_transaction_statuses(at)
134 }
135 None => self.fallback.current_transaction_statuses(at),
136 }
137 }
138
139 fn elasticity(&self, at: B::Hash) -> Option<Permill> {
140 match self.querier.storage_schema(at) {
141 Some(EthereumStorageSchema::V1) => {
142 SchemaV1StorageOverrideRef::new(&self.querier).elasticity(at)
143 }
144 Some(EthereumStorageSchema::V2) => {
145 SchemaV2StorageOverrideRef::new(&self.querier).elasticity(at)
146 }
147 Some(EthereumStorageSchema::V3) => {
148 SchemaV3StorageOverrideRef::new(&self.querier).elasticity(at)
149 }
150 None => self.fallback.elasticity(at),
151 }
152 }
153
154 fn is_eip1559(&self, at: B::Hash) -> bool {
155 match self.querier.storage_schema(at) {
156 Some(EthereumStorageSchema::V1) => {
157 SchemaV1StorageOverrideRef::new(&self.querier).is_eip1559(at)
158 }
159 Some(EthereumStorageSchema::V2) => {
160 SchemaV2StorageOverrideRef::new(&self.querier).is_eip1559(at)
161 }
162 Some(EthereumStorageSchema::V3) => {
163 SchemaV3StorageOverrideRef::new(&self.querier).is_eip1559(at)
164 }
165 None => self.fallback.is_eip1559(at),
166 }
167 }
168}