tempo_precompiles/tip20_factory/
dispatch.rs

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