aurora_evm/executor/stack/
precompile.rs1use crate::prelude::*;
2use crate::{Context, ExitError, ExitFatal, ExitReason, ExitRevert, ExitSucceed, Transfer};
3use primitive_types::{H160, H256};
4
5pub type PrecompileResult = Result<PrecompileOutput, PrecompileFailure>;
7
8#[derive(Debug, Eq, PartialEq, Clone)]
10pub struct PrecompileOutput {
11 pub exit_status: ExitSucceed,
12 pub output: Vec<u8>,
13}
14
15#[derive(Debug, Eq, PartialEq, Clone)]
17pub enum PrecompileFailure {
18 Error { exit_status: ExitError },
20 Revert {
23 exit_status: ExitRevert,
24 output: Vec<u8>,
25 },
26 Fatal { exit_status: ExitFatal },
28}
29
30impl From<ExitError> for PrecompileFailure {
31 fn from(error: ExitError) -> Self {
32 Self::Error { exit_status: error }
33 }
34}
35
36pub trait PrecompileHandle {
38 fn call(
41 &mut self,
42 to: H160,
43 transfer: Option<Transfer>,
44 input: Vec<u8>,
45 gas_limit: Option<u64>,
46 is_static: bool,
47 context: &Context,
48 ) -> (ExitReason, Vec<u8>);
49
50 fn record_cost(&mut self, cost: u64) -> Result<(), ExitError>;
55
56 fn record_external_cost(
61 &mut self,
62 ref_time: Option<u64>,
63 proof_size: Option<u64>,
64 storage_growth: Option<u64>,
65 ) -> Result<(), ExitError>;
66
67 fn refund_external_cost(&mut self, ref_time: Option<u64>, proof_size: Option<u64>);
69
70 fn remaining_gas(&self) -> u64;
72
73 fn log(&mut self, address: H160, topics: Vec<H256>, data: Vec<u8>) -> Result<(), ExitError>;
78
79 fn code_address(&self) -> H160;
81
82 fn input(&self) -> &[u8];
84
85 fn context(&self) -> &Context;
87
88 fn is_static(&self) -> bool;
90
91 fn gas_limit(&self) -> Option<u64>;
93}
94
95pub trait PrecompileSet {
100 fn execute(&self, handle: &mut impl PrecompileHandle) -> Option<PrecompileResult>;
103
104 fn is_precompile(&self, address: H160) -> bool;
108}
109
110impl PrecompileSet for () {
111 fn execute(&self, _: &mut impl PrecompileHandle) -> Option<PrecompileResult> {
112 None
113 }
114
115 fn is_precompile(&self, _: H160) -> bool {
116 false
117 }
118}
119
120pub type PrecompileFn =
128 fn(&[u8], Option<u64>, &Context, bool) -> Result<(PrecompileOutput, u64), PrecompileFailure>;
129
130impl PrecompileSet for BTreeMap<H160, PrecompileFn> {
131 fn execute(&self, handle: &mut impl PrecompileHandle) -> Option<PrecompileResult> {
132 let address = handle.code_address();
133
134 self.get(&address).map(|precompile| {
135 let input = handle.input();
136 let gas_limit = handle.gas_limit();
137 let context = handle.context();
138 let is_static = handle.is_static();
139
140 match (*precompile)(input, gas_limit, context, is_static) {
141 Ok((output, cost)) => {
142 handle.record_cost(cost)?;
143 Ok(output)
144 }
145 Err(err) => Err(err),
146 }
147 })
148 }
149
150 fn is_precompile(&self, address: H160) -> bool {
154 self.contains_key(&address)
155 }
156}