tempo_precompiles/storage/
mod.rs

1pub mod evm;
2pub mod hashmap;
3
4mod types;
5use tempo_chainspec::hardfork::TempoHardfork;
6pub use types::*;
7
8pub mod packing;
9pub use packing::FieldLocation;
10pub use types::mapping as slots;
11
12// Re-export extension traits for convenience
13pub use types::vec::VecSlotExt;
14
15use alloy::primitives::{Address, LogData, U256};
16use revm::state::{AccountInfo, Bytecode};
17
18use crate::error::TempoPrecompileError;
19
20/// Low-level storage provider for interacting with the EVM.
21pub trait PrecompileStorageProvider {
22    fn chain_id(&self) -> u64;
23    fn timestamp(&self) -> U256;
24    fn beneficiary(&self) -> Address;
25    fn set_code(&mut self, address: Address, code: Bytecode) -> Result<(), TempoPrecompileError>;
26    fn get_account_info(
27        &mut self,
28        address: Address,
29    ) -> Result<&'_ AccountInfo, TempoPrecompileError>;
30    fn sload(&mut self, address: Address, key: U256) -> Result<U256, TempoPrecompileError>;
31    fn tload(&mut self, address: Address, key: U256) -> Result<U256, TempoPrecompileError>;
32    fn sstore(
33        &mut self,
34        address: Address,
35        key: U256,
36        value: U256,
37    ) -> Result<(), TempoPrecompileError>;
38    fn tstore(
39        &mut self,
40        address: Address,
41        key: U256,
42        value: U256,
43    ) -> Result<(), TempoPrecompileError>;
44    fn emit_event(&mut self, address: Address, event: LogData) -> Result<(), TempoPrecompileError>;
45
46    /// Deducts gas from the remaining gas and return an error if the gas is insufficient.
47    fn deduct_gas(&mut self, gas: u64) -> Result<(), TempoPrecompileError>;
48
49    /// Add refund to the refund gas counter.
50    fn refund_gas(&mut self, gas: i64);
51
52    /// Returns the gas used so far.
53    fn gas_used(&self) -> u64;
54
55    /// Returns the gas refunded so far.
56    fn gas_refunded(&self) -> i64;
57
58    /// Currently active hardfork.
59    fn spec(&self) -> TempoHardfork;
60}
61
62/// Storage operations for a given (contract) address.
63pub trait StorageOps {
64    /// Performs an SSTORE operation at the provided slot, with the given value.
65    fn sstore(&mut self, slot: U256, value: U256) -> Result<(), TempoPrecompileError>;
66    /// Performs an SLOAD operation at the provided slot.
67    fn sload(&mut self, slot: U256) -> Result<U256, TempoPrecompileError>;
68}
69
70/// Trait providing access to a contract's address and storage provider.
71///
72/// Abstracts the common pattern of contracts needing both an address and a mutable reference
73/// to a storage provider. It is automatically implemented by the `#[contract]` macro.
74pub trait ContractStorage {
75    type Storage: PrecompileStorageProvider;
76
77    /// Contract address.
78    fn address(&self) -> Address;
79    /// Storage provider.
80    fn storage(&mut self) -> &mut Self::Storage;
81}
82
83/// Blanket implementation of `StorageOps` for all type that implement `ContractStorage`.
84/// Allows contracts to use `StorageOps` while delegating to `PrecompileStorageProvider`.
85impl<T> StorageOps for T
86where
87    T: ContractStorage,
88{
89    /// Performs an SSTORE operation at the provided slot, with the given value.
90    fn sstore(&mut self, slot: U256, value: U256) -> Result<(), TempoPrecompileError> {
91        let address = self.address();
92        self.storage().sstore(address, slot, value)
93    }
94
95    /// Performs an SLOAD operation at the provided slot.
96    fn sload(&mut self, slot: U256) -> Result<U256, TempoPrecompileError> {
97        let address = self.address();
98        self.storage().sload(address, slot)
99    }
100}