cfx_executor/internal_contract/components/
context.rs

1use crate::{
2    executive_observer::TracerTrait, stack::CallStackInfo, state::State,
3    substate::Substate,
4};
5use cfx_statedb::Result as DbResult;
6use cfx_types::{
7    address_util::AddressUtil, Address, AddressSpaceUtil, H256, U256,
8};
9use cfx_vm_types::{self as vm, ActionParams, Env, Spec};
10
11/// The internal contracts need to access the context parameter directly, e.g.,
12/// `foo(env, spec)`. But `foo(context.env(), context.spec())` will incur
13/// lifetime issue. The `InternalRefContext` contains the parameters required by
14/// the internal contracts.
15pub struct InternalRefContext<'a> {
16    pub env: &'a Env,
17    pub spec: &'a Spec,
18    pub callstack: &'a mut CallStackInfo,
19    pub state: &'a mut State,
20    pub substate: &'a mut Substate,
21    pub tracer: &'a mut dyn TracerTrait,
22    pub static_flag: bool,
23    pub depth: usize,
24}
25
26// The following implementation is copied from `executive/context.rs`. I know
27// it is not a good idea to implement the context interface again. We put it
28// here temporarily.
29impl<'a> InternalRefContext<'a> {
30    pub fn log(
31        &mut self, params: &ActionParams, spec: &Spec, topics: Vec<H256>,
32        data: Vec<u8>,
33    ) -> vm::Result<()> {
34        use primitives::log_entry::LogEntry;
35
36        if self.static_flag || self.callstack.in_reentrancy(spec) {
37            return Err(vm::Error::MutableCallInStaticContext);
38        }
39
40        let address = params.address;
41        self.substate.logs.push(LogEntry {
42            address,
43            topics,
44            data,
45            space: params.space,
46        });
47
48        Ok(())
49    }
50
51    pub fn set_storage(
52        &mut self, params: &ActionParams, key: Vec<u8>, value: U256,
53    ) -> vm::Result<()> {
54        let receiver = params.address.with_space(params.space);
55        self.state
56            .set_storage(
57                &receiver,
58                key,
59                value,
60                params.storage_owner,
61                self.substate,
62            )
63            .map_err(|e| e.into())
64    }
65
66    pub fn storage_at(
67        &mut self, params: &ActionParams, key: &[u8],
68    ) -> DbResult<U256> {
69        let receiver = params.address.with_space(params.space);
70        self.state.storage_at(&receiver, key).map_err(|e| e.into())
71    }
72
73    pub fn is_contract_address(&self, address: &Address) -> vm::Result<bool> {
74        Ok(address.is_contract_address())
75    }
76}