diff --git a/crates/katana/storage/provider/src/providers/fork/backend.rs b/crates/katana/storage/provider/src/providers/fork/backend.rs index 8e4f30c523..a19e923946 100644 --- a/crates/katana/storage/provider/src/providers/fork/backend.rs +++ b/crates/katana/storage/provider/src/providers/fork/backend.rs @@ -353,7 +353,25 @@ impl ContractInfoProvider for SharedStateProvider { impl StateProvider for SharedStateProvider { fn nonce(&self, address: ContractAddress) -> ProviderResult> { - if let nonce @ Some(_) = self.contract(address)?.map(|i| i.nonce) { + // TEMP: + // + // The nonce and class hash are stored in the same struct, so if we call either `nonce` or + // `class_hash_of_contract` first, the other would be filled with the default value. + // Currently, the data types that we're using doesn't allow us to distinguish between + // 'not fetched' vs the actual value. + // + // Right now, if the nonce value is 0, we couldn't distinguish whether that is the actual + // value or just the default value. So this filter is a pessimistic approach to always + // invalidate 0 nonce value in the cache. + // + // Meaning, if the nonce is 0, we always fetch the nonce from the forked provider, even if + // we already fetched it before. + // + // Similar story with `class_hash_of_contract` + // + if let nonce @ Some(_) = + self.contract(address)?.map(|i| i.nonce).filter(|n| n != &Nonce::ZERO) + { return Ok(nonce); } @@ -413,7 +431,10 @@ impl StateProvider for SharedStateProvider { &self, address: ContractAddress, ) -> ProviderResult> { - if let hash @ Some(_) = self.contract(address)?.map(|i| i.class_hash) { + // See comment at `nonce` for the explanation of this filter. + if let hash @ Some(_) = + self.contract(address)?.map(|i| i.class_hash).filter(|h| h != &ClassHash::ZERO) + { return Ok(hash); } diff --git a/crates/katana/storage/provider/src/providers/fork/state.rs b/crates/katana/storage/provider/src/providers/fork/state.rs index ba35a010d5..e265388b02 100644 --- a/crates/katana/storage/provider/src/providers/fork/state.rs +++ b/crates/katana/storage/provider/src/providers/fork/state.rs @@ -38,14 +38,22 @@ impl StateProvider for ForkedStateDb { &self, address: ContractAddress, ) -> ProviderResult> { - if let hash @ Some(_) = self.contract_state.read().get(&address).map(|i| i.class_hash) { + if let hash @ Some(_) = self + .contract_state + .read() + .get(&address) + .map(|i| i.class_hash) + .filter(|h| h != &ClassHash::ZERO) + { return Ok(hash); } StateProvider::class_hash_of_contract(&self.db, address) } fn nonce(&self, address: ContractAddress) -> ProviderResult> { - if let nonce @ Some(_) = self.contract_state.read().get(&address).map(|i| i.nonce) { + if let nonce @ Some(_) = + self.contract_state.read().get(&address).map(|i| i.nonce).filter(|n| n != &Nonce::ZERO) + { return Ok(nonce); } StateProvider::nonce(&self.db, address) @@ -148,7 +156,13 @@ impl ContractInfoProvider for ForkedSnapshot { impl StateProvider for ForkedSnapshot { fn nonce(&self, address: ContractAddress) -> ProviderResult> { - if let nonce @ Some(_) = self.inner.contract_state.get(&address).map(|info| info.nonce) { + if let nonce @ Some(_) = self + .inner + .contract_state + .get(&address) + .map(|info| info.nonce) + .filter(|n| n != &Nonce::ZERO) + { return Ok(nonce); } StateProvider::nonce(&self.inner.db, address) @@ -171,8 +185,12 @@ impl StateProvider for ForkedSnapshot { &self, address: ContractAddress, ) -> ProviderResult> { - if let class_hash @ Some(_) = - self.inner.contract_state.get(&address).map(|info| info.class_hash) + if let class_hash @ Some(_) = self + .inner + .contract_state + .get(&address) + .map(|info| info.class_hash) + .filter(|h| h != &ClassHash::ZERO) { return Ok(class_hash); }