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