aurora_engine_precompiles/
lib.rs

1#![cfg_attr(not(feature = "std"), no_std)]
2
3pub mod account_ids;
4pub mod alt_bn256;
5pub mod blake2;
6pub mod bls12_381;
7pub mod hash;
8pub mod identity;
9pub mod modexp;
10pub mod native;
11mod prelude;
12pub mod prepaid_gas;
13pub mod promise_result;
14pub mod random;
15pub mod secp256k1;
16pub mod secp256r1;
17mod utils;
18pub mod xcc;
19
20use crate::account_ids::{predecessor_account, CurrentAccount, PredecessorAccount};
21use crate::alt_bn256::{Bn256Add, Bn256Mul, Bn256Pair};
22use crate::blake2::Blake2F;
23use crate::hash::{RIPEMD160, SHA256};
24use crate::identity::Identity;
25use crate::modexp::ModExp;
26use crate::native::{exit_to_ethereum, exit_to_near, ExitToEthereum, ExitToNear};
27use crate::prelude::types::EthGas;
28use crate::prelude::{Vec, H256};
29use crate::prepaid_gas::PrepaidGas;
30use crate::random::RandomSeed;
31use crate::secp256k1::ECRecover;
32use crate::secp256r1::Secp256r1;
33use crate::xcc::CrossContractCall;
34use aurora_engine_modexp::ModExpAlgorithm;
35use aurora_engine_sdk::env::Env;
36use aurora_engine_sdk::io::IO;
37use aurora_engine_sdk::promise::ReadOnlyPromiseHandler;
38use aurora_engine_types::{account_id::AccountId, types::Address, vec, BTreeMap, BTreeSet, Box};
39use aurora_evm::backend::Log;
40use aurora_evm::executor::{
41    self,
42    stack::{PrecompileFailure, PrecompileHandle},
43};
44use aurora_evm::{Context, ExitError, ExitFatal, ExitSucceed};
45use promise_result::PromiseResult;
46use xcc::cross_contract_call;
47
48#[derive(Debug, Default, PartialEq, Eq)]
49pub struct PrecompileOutput {
50    pub cost: EthGas,
51    pub output: Vec<u8>,
52    pub logs: Vec<Log>,
53}
54
55impl PrecompileOutput {
56    #[must_use]
57    pub const fn without_logs(cost: EthGas, output: Vec<u8>) -> Self {
58        Self {
59            cost,
60            output,
61            logs: Vec::new(),
62        }
63    }
64}
65
66type EvmPrecompileResult = Result<PrecompileOutput, ExitError>;
67
68/// A precompiled function for use in the EVM.
69pub trait Precompile {
70    /// The required gas in order to run the precompile function.
71    fn required_gas(input: &[u8]) -> Result<EthGas, ExitError>
72    where
73        Self: Sized;
74
75    /// Runs the precompile function.
76    fn run(
77        &self,
78        input: &[u8],
79        target_gas: Option<EthGas>,
80        context: &Context,
81        is_static: bool,
82    ) -> EvmPrecompileResult;
83}
84
85pub trait HandleBasedPrecompile {
86    fn run_with_handle(
87        &self,
88        handle: &mut impl PrecompileHandle,
89    ) -> Result<PrecompileOutput, PrecompileFailure>;
90}
91
92/// Hard fork marker.
93pub trait HardFork {}
94
95/// Homestead hard fork marker.
96pub struct Homestead;
97
98/// Byzantium hard fork marker.
99pub struct Byzantium;
100
101/// Istanbul hard fork marker.
102pub struct Istanbul;
103
104/// Berlin hard fork marker.
105pub struct Berlin;
106
107/// Osaka hard fork marker.
108pub struct Osaka;
109
110impl HardFork for Homestead {}
111
112impl HardFork for Byzantium {}
113
114impl HardFork for Istanbul {}
115
116impl HardFork for Berlin {}
117
118impl HardFork for Osaka {}
119
120pub struct Precompiles<'a, I, E, H> {
121    pub all_precompiles: BTreeMap<Address, AllPrecompiles<'a, I, E, H>>,
122    pub paused_precompiles: BTreeSet<Address>,
123}
124
125impl<I, E, H> Precompiles<'_, I, E, H> {
126    fn is_paused(&self, address: &Address) -> bool {
127        self.paused_precompiles.contains(address)
128    }
129}
130
131impl<I: IO + Copy, E: Env, H: ReadOnlyPromiseHandler> executor::stack::PrecompileSet
132    for Precompiles<'_, I, E, H>
133{
134    fn execute(
135        &self,
136        handle: &mut impl PrecompileHandle,
137    ) -> Option<Result<executor::stack::PrecompileOutput, PrecompileFailure>> {
138        let address = Address::new(handle.code_address());
139
140        if self.is_paused(&address) {
141            return Some(Err(PrecompileFailure::Fatal {
142                exit_status: ExitFatal::Other(prelude::Cow::Borrowed("ERR_PAUSED")),
143            }));
144        }
145
146        let result = match self.all_precompiles.get(&address)? {
147            AllPrecompiles::ExitToNear(p) => process_precompile(p, handle),
148            AllPrecompiles::ExitToEthereum(p) => process_precompile(p, handle),
149            AllPrecompiles::PredecessorAccount(p) => process_precompile(p, handle),
150            AllPrecompiles::PrepaidGas(p) => process_precompile(p, handle),
151            AllPrecompiles::PromiseResult(p) => process_precompile(p, handle),
152            AllPrecompiles::CrossContractCall(p) => process_handle_based_precompile(p, handle),
153            AllPrecompiles::Generic(p) => process_precompile(p.as_ref(), handle),
154        };
155
156        Some(result.and_then(|output| post_process(output, handle)))
157    }
158
159    fn is_precompile(&self, address: prelude::H160) -> bool {
160        self.all_precompiles.contains_key(&Address::new(address))
161    }
162}
163
164fn process_precompile(
165    p: &dyn Precompile,
166    handle: &impl PrecompileHandle,
167) -> Result<PrecompileOutput, PrecompileFailure> {
168    let input = handle.input();
169    let gas_limit = handle.gas_limit();
170    let context = handle.context();
171    let is_static = handle.is_static();
172
173    p.run(input, gas_limit.map(EthGas::new), context, is_static)
174        .map_err(|exit_status| PrecompileFailure::Error { exit_status })
175}
176
177fn process_handle_based_precompile(
178    p: &impl HandleBasedPrecompile,
179    handle: &mut impl PrecompileHandle,
180) -> Result<PrecompileOutput, PrecompileFailure> {
181    p.run_with_handle(handle)
182}
183
184fn post_process(
185    output: PrecompileOutput,
186    handle: &mut impl PrecompileHandle,
187) -> Result<executor::stack::PrecompileOutput, PrecompileFailure> {
188    handle.record_cost(output.cost.as_u64())?;
189    for log in output.logs {
190        handle.log(log.address, log.topics, log.data)?;
191    }
192    Ok(executor::stack::PrecompileOutput {
193        exit_status: ExitSucceed::Returned,
194        output: output.output,
195    })
196}
197
198pub struct PrecompileConstructorContext<'a, I, E, H, M> {
199    pub current_account_id: AccountId,
200    pub random_seed: H256,
201    pub io: I,
202    pub env: &'a E,
203    pub promise_handler: H,
204    pub mod_exp_algorithm: prelude::PhantomData<M>,
205}
206
207impl<'a, I: IO + Copy, E: Env, H: ReadOnlyPromiseHandler> Precompiles<'a, I, E, H> {
208    #[allow(dead_code)]
209    pub fn new_homestead<M: ModExpAlgorithm + 'static>(
210        ctx: PrecompileConstructorContext<'a, I, E, H, M>,
211    ) -> Self {
212        let addresses = vec![
213            ECRecover::ADDRESS,
214            SHA256::ADDRESS,
215            RIPEMD160::ADDRESS,
216            RandomSeed::ADDRESS,
217            CurrentAccount::ADDRESS,
218        ];
219        let fun: Vec<Box<dyn Precompile>> = vec![
220            Box::new(ECRecover),
221            Box::new(SHA256),
222            Box::new(RIPEMD160),
223            Box::new(RandomSeed::new(ctx.random_seed)),
224            Box::new(CurrentAccount::new(ctx.current_account_id.clone())),
225        ];
226        let map = addresses
227            .into_iter()
228            .zip(fun)
229            .map(|(a, f)| (a, AllPrecompiles::Generic(f)))
230            .collect();
231        Self::with_generic_precompiles(map, ctx)
232    }
233
234    #[allow(dead_code)]
235    pub fn new_byzantium<M: ModExpAlgorithm + 'static>(
236        ctx: PrecompileConstructorContext<'a, I, E, H, M>,
237    ) -> Self {
238        let addresses = vec![
239            ECRecover::ADDRESS,
240            SHA256::ADDRESS,
241            RIPEMD160::ADDRESS,
242            Identity::ADDRESS,
243            ModExp::<Byzantium, M>::ADDRESS,
244            Bn256Add::<Byzantium>::ADDRESS,
245            Bn256Mul::<Byzantium>::ADDRESS,
246            Bn256Pair::<Byzantium>::ADDRESS,
247            RandomSeed::ADDRESS,
248            CurrentAccount::ADDRESS,
249        ];
250        let fun: Vec<Box<dyn Precompile>> = vec![
251            Box::new(ECRecover),
252            Box::new(SHA256),
253            Box::new(RIPEMD160),
254            Box::new(Identity),
255            Box::new(ModExp::<Byzantium, M>::new()),
256            Box::new(Bn256Add::<Byzantium>::new()),
257            Box::new(Bn256Mul::<Byzantium>::new()),
258            Box::new(Bn256Pair::<Byzantium>::new()),
259            Box::new(RandomSeed::new(ctx.random_seed)),
260            Box::new(CurrentAccount::new(ctx.current_account_id.clone())),
261        ];
262        let map = addresses
263            .into_iter()
264            .zip(fun)
265            .map(|(a, f)| (a, AllPrecompiles::Generic(f)))
266            .collect();
267
268        Self::with_generic_precompiles(map, ctx)
269    }
270
271    pub fn new_istanbul<M: ModExpAlgorithm + 'static>(
272        ctx: PrecompileConstructorContext<'a, I, E, H, M>,
273    ) -> Self {
274        let addresses = vec![
275            ECRecover::ADDRESS,
276            SHA256::ADDRESS,
277            RIPEMD160::ADDRESS,
278            Identity::ADDRESS,
279            ModExp::<Byzantium, M>::ADDRESS,
280            Bn256Add::<Istanbul>::ADDRESS,
281            Bn256Mul::<Istanbul>::ADDRESS,
282            Bn256Pair::<Istanbul>::ADDRESS,
283            Blake2F::ADDRESS,
284            RandomSeed::ADDRESS,
285            CurrentAccount::ADDRESS,
286        ];
287        let fun: Vec<Box<dyn Precompile>> = vec![
288            Box::new(ECRecover),
289            Box::new(SHA256),
290            Box::new(RIPEMD160),
291            Box::new(Identity),
292            Box::new(ModExp::<Byzantium, M>::new()),
293            Box::new(Bn256Add::<Istanbul>::new()),
294            Box::new(Bn256Mul::<Istanbul>::new()),
295            Box::new(Bn256Pair::<Istanbul>::new()),
296            Box::new(Blake2F),
297            Box::new(RandomSeed::new(ctx.random_seed)),
298            Box::new(CurrentAccount::new(ctx.current_account_id.clone())),
299        ];
300        let map = addresses
301            .into_iter()
302            .zip(fun)
303            .map(|(a, f)| (a, AllPrecompiles::Generic(f)))
304            .collect();
305
306        Self::with_generic_precompiles(map, ctx)
307    }
308
309    pub fn new_berlin<M: ModExpAlgorithm + 'static>(
310        ctx: PrecompileConstructorContext<'a, I, E, H, M>,
311    ) -> Self {
312        let addresses = vec![
313            ECRecover::ADDRESS,
314            SHA256::ADDRESS,
315            RIPEMD160::ADDRESS,
316            Identity::ADDRESS,
317            ModExp::<Berlin, M>::ADDRESS,
318            Bn256Add::<Istanbul>::ADDRESS,
319            Bn256Mul::<Istanbul>::ADDRESS,
320            Bn256Pair::<Istanbul>::ADDRESS,
321            Blake2F::ADDRESS,
322            RandomSeed::ADDRESS,
323            CurrentAccount::ADDRESS,
324        ];
325        let fun: Vec<Box<dyn Precompile>> = vec![
326            Box::new(ECRecover),
327            Box::new(SHA256),
328            Box::new(RIPEMD160),
329            Box::new(Identity),
330            Box::new(ModExp::<Berlin, M>::new()),
331            Box::new(Bn256Add::<Istanbul>::new()),
332            Box::new(Bn256Mul::<Istanbul>::new()),
333            Box::new(Bn256Pair::<Istanbul>::new()),
334            Box::new(Blake2F),
335            Box::new(RandomSeed::new(ctx.random_seed)),
336            Box::new(CurrentAccount::new(ctx.current_account_id.clone())),
337        ];
338        let map = addresses
339            .into_iter()
340            .zip(fun)
341            .map(|(a, f)| (a, AllPrecompiles::Generic(f)))
342            .collect();
343
344        Self::with_generic_precompiles(map, ctx)
345    }
346
347    pub fn new_london<M: ModExpAlgorithm + 'static>(
348        ctx: PrecompileConstructorContext<'a, I, E, H, M>,
349    ) -> Self {
350        // no precompile changes in London HF
351        Self::new_berlin(ctx)
352    }
353
354    /// Prague hard fork includes `BLS12-381` precompiles.
355    ///
356    /// [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537)
357    pub fn new_prague<M: ModExpAlgorithm + 'static>(
358        ctx: PrecompileConstructorContext<'a, I, E, H, M>,
359    ) -> Self {
360        let addresses = vec![
361            ECRecover::ADDRESS,
362            SHA256::ADDRESS,
363            RIPEMD160::ADDRESS,
364            Identity::ADDRESS,
365            ModExp::<Berlin, M>::ADDRESS,
366            Bn256Add::<Istanbul>::ADDRESS,
367            Bn256Mul::<Istanbul>::ADDRESS,
368            Bn256Pair::<Istanbul>::ADDRESS,
369            Blake2F::ADDRESS,
370            RandomSeed::ADDRESS,
371            CurrentAccount::ADDRESS,
372            bls12_381::BlsG1Add::ADDRESS,
373            bls12_381::BlsG1Msm::ADDRESS,
374            bls12_381::BlsG2Add::ADDRESS,
375            bls12_381::BlsG2Msm::ADDRESS,
376            bls12_381::BlsPairingCheck::ADDRESS,
377            bls12_381::BlsMapFpToG1::ADDRESS,
378            bls12_381::BlsMapFp2ToG2::ADDRESS,
379        ];
380        let fun: Vec<Box<dyn Precompile>> = vec![
381            Box::new(ECRecover),
382            Box::new(SHA256),
383            Box::new(RIPEMD160),
384            Box::new(Identity),
385            Box::new(ModExp::<Berlin, M>::new()),
386            Box::new(Bn256Add::<Istanbul>::new()),
387            Box::new(Bn256Mul::<Istanbul>::new()),
388            Box::new(Bn256Pair::<Istanbul>::new()),
389            Box::new(Blake2F),
390            Box::new(RandomSeed::new(ctx.random_seed)),
391            Box::new(CurrentAccount::new(ctx.current_account_id.clone())),
392            Box::new(bls12_381::BlsG1Add),
393            Box::new(bls12_381::BlsG1Msm),
394            Box::new(bls12_381::BlsG2Add),
395            Box::new(bls12_381::BlsG2Msm),
396            Box::new(bls12_381::BlsPairingCheck),
397            Box::new(bls12_381::BlsMapFpToG1),
398            Box::new(bls12_381::BlsMapFp2ToG2),
399        ];
400        let map = addresses
401            .into_iter()
402            .zip(fun)
403            .map(|(a, f)| (a, AllPrecompiles::Generic(f)))
404            .collect();
405
406        Self::with_generic_precompiles(map, ctx)
407    }
408
409    pub fn new_osaka<M: ModExpAlgorithm + 'static>(
410        ctx: PrecompileConstructorContext<'a, I, E, H, M>,
411    ) -> Self {
412        let addresses = vec![
413            ECRecover::ADDRESS,
414            SHA256::ADDRESS,
415            RIPEMD160::ADDRESS,
416            Identity::ADDRESS,
417            ModExp::<Osaka, M>::ADDRESS,
418            Bn256Add::<Istanbul>::ADDRESS,
419            Bn256Mul::<Istanbul>::ADDRESS,
420            Bn256Pair::<Istanbul>::ADDRESS,
421            Blake2F::ADDRESS,
422            RandomSeed::ADDRESS,
423            CurrentAccount::ADDRESS,
424            bls12_381::BlsG1Add::ADDRESS,
425            bls12_381::BlsG1Msm::ADDRESS,
426            bls12_381::BlsG2Add::ADDRESS,
427            bls12_381::BlsG2Msm::ADDRESS,
428            bls12_381::BlsPairingCheck::ADDRESS,
429            bls12_381::BlsMapFpToG1::ADDRESS,
430            bls12_381::BlsMapFp2ToG2::ADDRESS,
431            Secp256r1::ADDRESS,
432        ];
433        let fun: Vec<Box<dyn Precompile>> = vec![
434            Box::new(ECRecover),
435            Box::new(SHA256),
436            Box::new(RIPEMD160),
437            Box::new(Identity),
438            Box::new(ModExp::<Osaka, M>::new()),
439            Box::new(Bn256Add::<Istanbul>::new()),
440            Box::new(Bn256Mul::<Istanbul>::new()),
441            Box::new(Bn256Pair::<Istanbul>::new()),
442            Box::new(Blake2F),
443            Box::new(RandomSeed::new(ctx.random_seed)),
444            Box::new(CurrentAccount::new(ctx.current_account_id.clone())),
445            Box::new(bls12_381::BlsG1Add),
446            Box::new(bls12_381::BlsG1Msm),
447            Box::new(bls12_381::BlsG2Add),
448            Box::new(bls12_381::BlsG2Msm),
449            Box::new(bls12_381::BlsPairingCheck),
450            Box::new(bls12_381::BlsMapFpToG1),
451            Box::new(bls12_381::BlsMapFp2ToG2),
452            Box::new(Secp256r1),
453        ];
454        let map = addresses
455            .into_iter()
456            .zip(fun)
457            .map(|(a, f)| (a, AllPrecompiles::Generic(f)))
458            .collect();
459
460        Self::with_generic_precompiles(map, ctx)
461    }
462
463    fn with_generic_precompiles<M: ModExpAlgorithm + 'static>(
464        mut generic_precompiles: BTreeMap<Address, AllPrecompiles<'a, I, E, H>>,
465        ctx: PrecompileConstructorContext<'a, I, E, H, M>,
466    ) -> Self {
467        let near_exit = ExitToNear::new(ctx.current_account_id.clone(), ctx.io);
468        let ethereum_exit = ExitToEthereum::new(ctx.io);
469        let cross_contract_call = CrossContractCall::new(ctx.current_account_id, ctx.io);
470        let predecessor_account_id = PredecessorAccount::new(ctx.env);
471        let prepaid_gas = PrepaidGas::new(ctx.env);
472        let promise_results = PromiseResult::new(ctx.promise_handler);
473
474        generic_precompiles.insert(exit_to_near::ADDRESS, AllPrecompiles::ExitToNear(near_exit));
475        generic_precompiles.insert(
476            exit_to_ethereum::ADDRESS,
477            AllPrecompiles::ExitToEthereum(ethereum_exit),
478        );
479        generic_precompiles.insert(
480            cross_contract_call::ADDRESS,
481            AllPrecompiles::CrossContractCall(cross_contract_call),
482        );
483        generic_precompiles.insert(
484            predecessor_account::ADDRESS,
485            AllPrecompiles::PredecessorAccount(predecessor_account_id),
486        );
487        generic_precompiles.insert(
488            prepaid_gas::ADDRESS,
489            AllPrecompiles::PrepaidGas(prepaid_gas),
490        );
491        generic_precompiles.insert(
492            promise_result::ADDRESS,
493            AllPrecompiles::PromiseResult(promise_results),
494        );
495
496        Self {
497            all_precompiles: generic_precompiles,
498            paused_precompiles: BTreeSet::new(),
499        }
500    }
501}
502
503pub enum AllPrecompiles<'a, I, E, H> {
504    ExitToNear(ExitToNear<I>),
505    ExitToEthereum(ExitToEthereum<I>),
506    CrossContractCall(CrossContractCall<I>),
507    PredecessorAccount(PredecessorAccount<'a, E>),
508    PrepaidGas(PrepaidGas<'a, E>),
509    PromiseResult(PromiseResult<H>),
510    Generic(Box<dyn Precompile>),
511}
512
513const fn make_h256(x: u128, y: u128) -> H256 {
514    let x_bytes = x.to_be_bytes();
515    let y_bytes = y.to_be_bytes();
516    H256([
517        x_bytes[0],
518        x_bytes[1],
519        x_bytes[2],
520        x_bytes[3],
521        x_bytes[4],
522        x_bytes[5],
523        x_bytes[6],
524        x_bytes[7],
525        x_bytes[8],
526        x_bytes[9],
527        x_bytes[10],
528        x_bytes[11],
529        x_bytes[12],
530        x_bytes[13],
531        x_bytes[14],
532        x_bytes[15],
533        y_bytes[0],
534        y_bytes[1],
535        y_bytes[2],
536        y_bytes[3],
537        y_bytes[4],
538        y_bytes[5],
539        y_bytes[6],
540        y_bytes[7],
541        y_bytes[8],
542        y_bytes[9],
543        y_bytes[10],
544        y_bytes[11],
545        y_bytes[12],
546        y_bytes[13],
547        y_bytes[14],
548        y_bytes[15],
549    ])
550}
551
552#[cfg(test)]
553mod tests {
554    use crate::prelude::H160;
555    use crate::{prelude, Byzantium, Istanbul};
556    use prelude::types::Address;
557
558    #[test]
559    fn test_precompile_addresses() {
560        assert_eq!(super::secp256k1::ECRecover::ADDRESS, u8_to_address(1));
561        assert_eq!(super::hash::SHA256::ADDRESS, u8_to_address(2));
562        assert_eq!(super::hash::RIPEMD160::ADDRESS, u8_to_address(3));
563        assert_eq!(super::identity::Identity::ADDRESS, u8_to_address(4));
564        assert_eq!(super::ModExp::<Byzantium>::ADDRESS, u8_to_address(5));
565        assert_eq!(super::Bn256Add::<Istanbul>::ADDRESS, u8_to_address(6));
566        assert_eq!(super::Bn256Mul::<Istanbul>::ADDRESS, u8_to_address(7));
567        assert_eq!(super::Bn256Pair::<Istanbul>::ADDRESS, u8_to_address(8));
568        assert_eq!(super::blake2::Blake2F::ADDRESS, u8_to_address(9));
569    }
570
571    #[test]
572    #[allow(clippy::too_many_lines)]
573    fn test_paused_precompiles_throws_error() {
574        use crate::{
575            AllPrecompiles, Context, EvmPrecompileResult, ExitError, Precompile, PrecompileOutput,
576            Precompiles,
577        };
578        use aurora_engine_sdk::env::Fixed;
579        use aurora_engine_sdk::promise::Noop;
580        use aurora_engine_test_doubles::io::StoragePointer;
581        use aurora_engine_types::types::EthGas;
582        use aurora_evm::executor::stack::{PrecompileFailure, PrecompileHandle, PrecompileSet};
583        use aurora_evm::{ExitFatal, ExitReason, Transfer};
584
585        struct MockPrecompile;
586
587        impl Precompile for MockPrecompile {
588            fn required_gas(_input: &[u8]) -> Result<EthGas, ExitError>
589            where
590                Self: Sized,
591            {
592                Ok(EthGas::new(0))
593            }
594
595            fn run(
596                &self,
597                _input: &[u8],
598                _target_gas: Option<EthGas>,
599                _context: &Context,
600                _is_static: bool,
601            ) -> EvmPrecompileResult {
602                Ok(PrecompileOutput::default())
603            }
604        }
605
606        struct MockPrecompileHandle {
607            code_address: H160,
608        }
609
610        impl MockPrecompileHandle {
611            pub const fn new(code_address: H160) -> Self {
612                Self { code_address }
613            }
614        }
615
616        impl PrecompileHandle for MockPrecompileHandle {
617            fn call(
618                &mut self,
619                _to: H160,
620                _transfer: Option<Transfer>,
621                _input: Vec<u8>,
622                _gas_limit: Option<u64>,
623                _is_static: bool,
624                _context: &Context,
625            ) -> (ExitReason, Vec<u8>) {
626                unimplemented!()
627            }
628
629            fn record_cost(&mut self, _cost: u64) -> Result<(), ExitError> {
630                unimplemented!()
631            }
632
633            fn record_external_cost(
634                &mut self,
635                _ref_time: Option<u64>,
636                _proof_size: Option<u64>,
637                _storage_growth: Option<u64>,
638            ) -> Result<(), ExitError> {
639                unimplemented!()
640            }
641
642            fn refund_external_cost(&mut self, _ref_time: Option<u64>, _proof_size: Option<u64>) {
643                unimplemented!()
644            }
645
646            fn remaining_gas(&self) -> u64 {
647                unimplemented!()
648            }
649
650            fn log(
651                &mut self,
652                _address: H160,
653                _topics: Vec<aurora_engine_types::H256>,
654                _data: Vec<u8>,
655            ) -> Result<(), ExitError> {
656                unimplemented!()
657            }
658
659            fn code_address(&self) -> H160 {
660                self.code_address
661            }
662
663            fn input(&self) -> &[u8] {
664                unimplemented!()
665            }
666
667            fn context(&self) -> &Context {
668                unimplemented!()
669            }
670
671            fn is_static(&self) -> bool {
672                unimplemented!()
673            }
674
675            fn gas_limit(&self) -> Option<u64> {
676                unimplemented!()
677            }
678        }
679
680        let precompile_address = Address::default();
681        let precompile: AllPrecompiles<StoragePointer, Fixed, Noop> =
682            AllPrecompiles::Generic(Box::new(MockPrecompile));
683
684        let precompiles: Precompiles<StoragePointer, Fixed, Noop> = Precompiles {
685            all_precompiles: {
686                let mut map = prelude::BTreeMap::new();
687                map.insert(precompile_address, precompile);
688                map
689            },
690            paused_precompiles: {
691                let mut set = prelude::BTreeSet::new();
692                set.insert(precompile_address);
693                set
694            },
695        };
696        let mut precompile_handle = MockPrecompileHandle::new(precompile_address.raw());
697
698        let result = precompiles
699            .execute(&mut precompile_handle)
700            .expect("result must contain error but is empty");
701        let actual_failure = result.expect_err("result must contain failure but is successful");
702        let expected_failure = PrecompileFailure::Fatal {
703            exit_status: ExitFatal::Other(prelude::Cow::Borrowed("ERR_PAUSED")),
704        };
705
706        assert_eq!(expected_failure, actual_failure);
707    }
708
709    const fn u8_to_address(x: u8) -> Address {
710        let mut bytes = [0u8; 20];
711        bytes[19] = x;
712        Address::new(H160(bytes))
713    }
714}