precompile_utils/testing/
modifier.rs1use crate::{
20 solidity::codec::Writer,
21 testing::{decode_revert_message, MockHandle},
22};
23use fp_evm::{Context, PrecompileFailure, PrecompileSet};
24use sp_core::{H160, U256};
25
26pub struct PrecompilesModifierTester<P> {
27 precompiles: P,
28 handle: MockHandle,
29}
30
31impl<P: PrecompileSet> PrecompilesModifierTester<P> {
32 pub fn new(precompiles: P, from: impl Into<H160>, to: impl Into<H160>) -> Self {
33 let to = to.into();
34 let mut handle = MockHandle::new(
35 to,
36 Context {
37 address: to,
38 caller: from.into(),
39 apparent_value: U256::zero(),
40 },
41 );
42
43 handle.gas_limit = u64::MAX;
44
45 Self {
46 precompiles,
47 handle,
48 }
49 }
50
51 fn is_view(&mut self, selector: u32) -> bool {
52 let handle = &mut self.handle;
54 handle.is_static = true;
55 handle.context.apparent_value = U256::zero();
56 handle.input = Writer::new_with_selector(selector).build();
57
58 let res = self.precompiles.execute(handle);
59
60 match res {
61 Some(Err(PrecompileFailure::Revert { output, .. })) => {
62 let decoded = decode_revert_message(&output);
63
64 dbg!(decoded) != b"Can't call non-static function in static context"
65 }
66 Some(_) => true,
67 None => panic!("tried to check view modifier on unknown precompile"),
68 }
69 }
70
71 fn is_payable(&mut self, selector: u32) -> bool {
72 let handle = &mut self.handle;
74 handle.is_static = false;
75 handle.context.apparent_value = U256::one();
76 handle.input = Writer::new_with_selector(selector).build();
77
78 let res = self.precompiles.execute(handle);
79
80 match res {
81 Some(Err(PrecompileFailure::Revert { output, .. })) => {
82 let decoded = decode_revert_message(&output);
83
84 decoded != b"Function is not payable"
85 }
86 Some(_) => true,
87 None => panic!("tried to check payable modifier on unknown precompile"),
88 }
89 }
90
91 pub fn test_view_modifier(&mut self, selectors: &[u32]) {
92 for &s in selectors {
93 assert!(
94 self.is_view(s),
95 "Function doesn't behave like a view function."
96 );
97 assert!(
98 !self.is_payable(s),
99 "Function doesn't behave like a non-payable function."
100 )
101 }
102 }
103
104 pub fn test_payable_modifier(&mut self, selectors: &[u32]) {
105 for &s in selectors {
106 assert!(
107 !self.is_view(s),
108 "Function doesn't behave like a non-view function."
109 );
110 assert!(
111 self.is_payable(s),
112 "Function doesn't behave like a payable function."
113 );
114 }
115 }
116
117 pub fn test_default_modifier(&mut self, selectors: &[u32]) {
118 for &s in selectors {
119 assert!(
120 !self.is_view(s),
121 "Function doesn't behave like a non-view function."
122 );
123 assert!(
124 !self.is_payable(s),
125 "Function doesn't behave like a non-payable function."
126 );
127 }
128 }
129}