1
// Copyright 2019-2025 PureStake Inc.
2
// This file is part of Moonbeam.
3

            
4
// Moonbeam is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8

            
9
// Moonbeam is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13

            
14
// You should have received a copy of the GNU General Public License
15
// along with Moonbeam.  If not, see <http://www.gnu.org/licenses/>.
16

            
17
extern crate alloc;
18

            
19
use alloc::vec::Vec;
20
use ethereum_types::{H160, H256, U256};
21
use evm::ExitReason;
22
use parity_scale_codec::{Decode, Encode};
23

            
24
#[derive(Clone, Debug, Encode, Decode, PartialEq, Eq)]
25
pub struct Transfer {
26
	/// Source address.
27
	pub source: H160,
28
	/// Target address.
29
	pub target: H160,
30
	/// Transfer value.
31
	pub value: U256,
32
}
33

            
34
impl From<evm_runtime::Transfer> for Transfer {
35
	fn from(i: evm_runtime::Transfer) -> Self {
36
		Self {
37
			source: i.source,
38
			target: i.target,
39
			value: i.value,
40
		}
41
	}
42
}
43

            
44
#[derive(Clone, Copy, Eq, PartialEq, Debug, Encode, Decode)]
45
pub enum CreateScheme {
46
	/// Legacy create scheme of `CREATE`.
47
	Legacy {
48
		/// Caller of the create.
49
		caller: H160,
50
	},
51
	/// Create scheme of `CREATE2`.
52
	Create2 {
53
		/// Caller of the create.
54
		caller: H160,
55
		/// Code hash.
56
		code_hash: H256,
57
		/// Salt.
58
		salt: H256,
59
	},
60
	/// Create at a fixed location.
61
	Fixed(H160),
62
}
63

            
64
impl From<evm_runtime::CreateScheme> for CreateScheme {
65
	fn from(i: evm_runtime::CreateScheme) -> Self {
66
		match i {
67
			evm_runtime::CreateScheme::Legacy { caller } => Self::Legacy { caller },
68
			evm_runtime::CreateScheme::Create2 {
69
				caller,
70
				code_hash,
71
				salt,
72
			} => Self::Create2 {
73
				caller,
74
				code_hash,
75
				salt,
76
			},
77
			evm_runtime::CreateScheme::Fixed(address) => Self::Fixed(address),
78
		}
79
	}
80
}
81

            
82
#[derive(Debug, Clone, Encode, Decode, PartialEq, Eq)]
83
pub enum EvmEvent {
84
	Call {
85
		code_address: H160,
86
		transfer: Option<Transfer>,
87
		input: Vec<u8>,
88
		target_gas: Option<u64>,
89
		is_static: bool,
90
		context: super::Context,
91
	},
92
	Create {
93
		caller: H160,
94
		address: H160,
95
		scheme: CreateScheme,
96
		value: U256,
97
		init_code: Vec<u8>,
98
		target_gas: Option<u64>,
99
	},
100
	Suicide {
101
		address: H160,
102
		target: H160,
103
		balance: U256,
104
	},
105
	Exit {
106
		reason: ExitReason,
107
		return_value: Vec<u8>,
108
	},
109
	TransactCall {
110
		caller: H160,
111
		address: H160,
112
		value: U256,
113
		data: Vec<u8>,
114
		gas_limit: u64,
115
	},
116
	TransactCreate {
117
		caller: H160,
118
		value: U256,
119
		init_code: Vec<u8>,
120
		gas_limit: u64,
121
		address: H160,
122
	},
123
	TransactCreate2 {
124
		caller: H160,
125
		value: U256,
126
		init_code: Vec<u8>,
127
		salt: H256,
128
		gas_limit: u64,
129
		address: H160,
130
	},
131
	PrecompileSubcall {
132
		code_address: H160,
133
		transfer: Option<Transfer>,
134
		input: Vec<u8>,
135
		target_gas: Option<u64>,
136
		is_static: bool,
137
		context: super::Context,
138
	},
139
	Log {
140
		address: H160,
141
		topics: Vec<H256>,
142
		data: Vec<u8>,
143
	},
144
}
145

            
146
#[cfg(feature = "evm-tracing")]
147
impl<'a> From<evm::tracing::Event<'a>> for EvmEvent {
148
	fn from(i: evm::tracing::Event<'a>) -> Self {
149
		match i {
150
			evm::tracing::Event::Call {
151
				code_address,
152
				transfer,
153
				input,
154
				target_gas,
155
				is_static,
156
				context,
157
			} => Self::Call {
158
				code_address,
159
				transfer: if let Some(transfer) = transfer {
160
					Some(transfer.clone().into())
161
				} else {
162
					None
163
				},
164
				input: input.to_vec(),
165
				target_gas,
166
				is_static,
167
				context: context.clone().into(),
168
			},
169
			evm::tracing::Event::Create {
170
				caller,
171
				address,
172
				scheme,
173
				value,
174
				init_code,
175
				target_gas,
176
			} => Self::Create {
177
				caller,
178
				address,
179
				scheme: scheme.into(),
180
				value,
181
				init_code: init_code.to_vec(),
182
				target_gas,
183
			},
184
			evm::tracing::Event::Suicide {
185
				address,
186
				target,
187
				balance,
188
			} => Self::Suicide {
189
				address,
190
				target,
191
				balance,
192
			},
193
			evm::tracing::Event::Exit {
194
				reason,
195
				return_value,
196
			} => Self::Exit {
197
				reason: reason.clone(),
198
				return_value: return_value.to_vec(),
199
			},
200
			evm::tracing::Event::TransactCall {
201
				caller,
202
				address,
203
				value,
204
				data,
205
				gas_limit,
206
			} => Self::TransactCall {
207
				caller,
208
				address,
209
				value,
210
				data: data.to_vec(),
211
				gas_limit,
212
			},
213
			evm::tracing::Event::TransactCreate {
214
				caller,
215
				value,
216
				init_code,
217
				gas_limit,
218
				address,
219
			} => Self::TransactCreate {
220
				caller,
221
				value,
222
				init_code: init_code.to_vec(),
223
				gas_limit,
224
				address,
225
			},
226
			evm::tracing::Event::TransactCreate2 {
227
				caller,
228
				value,
229
				init_code,
230
				salt,
231
				gas_limit,
232
				address,
233
			} => Self::TransactCreate2 {
234
				caller,
235
				value,
236
				init_code: init_code.to_vec(),
237
				salt,
238
				gas_limit,
239
				address,
240
			},
241
			evm::tracing::Event::PrecompileSubcall {
242
				code_address,
243
				transfer,
244
				input,
245
				target_gas,
246
				is_static,
247
				context,
248
			} => Self::PrecompileSubcall {
249
				code_address,
250
				transfer: if let Some(transfer) = transfer {
251
					Some(transfer.clone().into())
252
				} else {
253
					None
254
				},
255
				input: input.to_vec(),
256
				target_gas,
257
				is_static,
258
				context: context.clone().into(),
259
			},
260
			evm::tracing::Event::Log {
261
				address,
262
				topics,
263
				data,
264
			} => Self::Log {
265
				address,
266
				topics: topics.to_vec(),
267
				data: data.to_vec(),
268
			},
269
		}
270
	}
271
}