aurora_engine_precompiles/
identity.rs1use aurora_evm::{Context, ExitError};
2
3use crate::prelude::types::{Address, EthGas, make_address};
4use crate::{EvmPrecompileResult, Precompile, PrecompileOutput, utils};
5
6mod costs {
8 use aurora_engine_types::types::EthGas;
9
10 pub(super) const IDENTITY_BASE: EthGas = EthGas::new(15);
12
13 pub(super) const IDENTITY_PER_WORD: EthGas = EthGas::new(3);
15}
16
17mod consts {
18 pub(super) const IDENTITY_WORD_LEN: u64 = 32;
20}
21
22pub struct Identity;
23
24impl Identity {
25 pub const ADDRESS: Address = make_address(0, 4);
26}
27
28impl Precompile for Identity {
29 fn required_gas(input: &[u8]) -> Result<EthGas, ExitError> {
30 let input_len = u64::try_from(input.len()).map_err(utils::err_usize_conv)?;
31 Ok(
32 input_len.div_ceil(consts::IDENTITY_WORD_LEN) * costs::IDENTITY_PER_WORD
33 + costs::IDENTITY_BASE,
34 )
35 }
36
37 fn run(
42 &self,
43 input: &[u8],
44 target_gas: Option<EthGas>,
45 _context: &Context,
46 _is_static: bool,
47 ) -> EvmPrecompileResult {
48 let cost = Self::required_gas(input)?;
49 if let Some(target_gas) = target_gas {
50 if cost > target_gas {
51 return Err(ExitError::OutOfGas);
52 }
53 }
54
55 Ok(PrecompileOutput::without_logs(cost, input.to_vec()))
56 }
57}
58
59#[cfg(test)]
60mod tests {
61 use aurora_evm::ExitError;
62
63 use crate::utils::new_context;
64
65 use super::*;
66
67 #[test]
68 fn test_identity() {
69 let input = [0u8, 1, 2, 3];
70
71 let expected = input[0..2].to_vec();
72 let res = Identity
73 .run(&input[0..2], Some(EthGas::new(18)), &new_context(), false)
74 .unwrap()
75 .output;
76 assert_eq!(res, expected);
77
78 let expected = input.to_vec();
79 let res = Identity
80 .run(&input, Some(EthGas::new(18)), &new_context(), false)
81 .unwrap()
82 .output;
83 assert_eq!(res, expected);
84
85 let res = Identity.run(&input[0..2], Some(EthGas::new(17)), &new_context(), false);
87
88 assert!(matches!(res, Err(ExitError::OutOfGas)));
89
90 let input = [
92 0u8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
93 24, 25, 26, 27, 28, 29, 30, 31, 32,
94 ];
95 let res = Identity
96 .run(&input, Some(EthGas::new(21)), &new_context(), false)
97 .unwrap()
98 .output;
99 assert_eq!(res, input.to_vec());
100 }
101}