tempo_precompiles/nonce/
dispatch.rs1use 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}