tempo_precompiles/nonce/
dispatch.rs

1use crate::{
2    Precompile, fill_precompile_output, input_cost, nonce::NonceManager, unknown_selector, view,
3};
4use alloy::{primitives::Address, sol_types::SolCall};
5use revm::precompile::{PrecompileError, PrecompileResult};
6
7use super::INonce;
8
9impl Precompile for NonceManager {
10    fn call(&mut self, calldata: &[u8], _msg_sender: Address) -> PrecompileResult {
11        self.storage
12            .deduct_gas(input_cost(calldata.len()))
13            .map_err(|_| PrecompileError::OutOfGas)?;
14
15        let selector: [u8; 4] = calldata
16            .get(..4)
17            .ok_or_else(|| {
18                PrecompileError::Other("Invalid input: missing function selector".into())
19            })?
20            .try_into()
21            .unwrap();
22
23        let result = match selector {
24            INonce::getNonceCall::SELECTOR => {
25                view::<INonce::getNonceCall>(calldata, |call| self.get_nonce(call))
26            }
27            INonce::getActiveNonceKeyCountCall::SELECTOR => {
28                view::<INonce::getActiveNonceKeyCountCall>(calldata, |call| {
29                    self.get_active_nonce_key_count(call)
30                })
31            }
32            _ => unknown_selector(selector, self.storage.gas_used(), self.storage.spec()),
33        };
34
35        result.map(|res| fill_precompile_output(res, &mut self.storage))
36    }
37}
38
39#[cfg(test)]
40mod tests {
41    use super::*;
42    use crate::{
43        storage::{StorageCtx, hashmap::HashMapStorageProvider},
44        test_util::{assert_full_coverage, check_selector_coverage},
45    };
46    use tempo_contracts::precompiles::INonce::INonceCalls;
47
48    #[test]
49    fn test_nonce_selector_coverage() -> eyre::Result<()> {
50        let mut storage = HashMapStorageProvider::new(1);
51        StorageCtx::enter(&mut storage, || {
52            let mut nonce_manager = NonceManager::new();
53
54            let unsupported = check_selector_coverage(
55                &mut nonce_manager,
56                INonceCalls::SELECTORS,
57                "INonce",
58                INonceCalls::name_by_selector,
59            );
60
61            assert_full_coverage([unsupported]);
62            Ok(())
63        })
64    }
65}