Objective

To implement transient storage (tstorage) in the FVM, allowing data to persist within the scope of a single transaction and accessible across multiple calls within that transaction. This data should reset automatically at the end of each transaction.

Proposed Implementation

At the level where memory tracking occurs for EVM actor execution, we find the System struct:

/// Platform Abstraction Layer bridging the FVM to EVM
pub struct System<'r, RT: Runtime> {
    pub rt: &'r RT,

    /// Current bytecode (blake2b256(ipld_raw(bytecode)), keccak256(bytecode))
    bytecode: Option<EvmBytecode>,
    /// EVM storage slots for contract state
    slots: StateKamt<RT::Blockstore>,
    /// Contract's nonce (incremented for new actors)
    pub(crate) nonce: u64,
    /// Last saved state root. None if the current state hasn’t been saved yet.
    saved_state_root: Option<Cid>,
    /// Read-only (staticcall) context
    pub readonly: bool,
    /// Chain randomness from the current epoch
    randomness: Option<[u8; 32]>,

    /// If the actor is a "zombie" (selfdestructed but still executing)
    pub(crate) tombstone: Option<Tombstone>,
}

To implement tstorage, we propose adding a field for transient_storage:

/// Transient storage, flushed at the end of each message execution
transient_storage: TransientStorage,

The TransientStorage struct can mirror Memory (in actors/evm/src/interpreter/memory.rs), adapted for transaction-scoped data that persists across function calls in the same transaction but is cleared afterward.

Expected Behavior

Potential Concerns

A concern with placing transient_storage in System is that the System object may be instantiated multiple times within a single transaction. For example, if a contract deploys a new contract within the same transaction, each contract could get its own System instance, leading to separate transient_storage instances. This would disrupt the goal of having a single shared transient storage for the entire transaction context.

If System is indeed instantiated multiple times within a transaction, then System may not be the appropriate layer for TransientStorage. Instead, we may need a higher-level context or transaction manager to ensure transient_storage persists consistently across nested calls and contract creations within the transaction.

Summary