anvil_polkadot/api_server/
revive_conversions.rs1use alloy_eips::{BlockId, BlockNumberOrTag};
2use alloy_primitives::{Address, B256};
3use alloy_rpc_types::{
4 AccessList, FilterBlockOption, FilterSet, SignedAuthorization, Topic, TransactionRequest,
5 trace::geth::{
6 AccountState, CallFrame, CallLogFrame, DiffMode, GethDebugBuiltInTracerType,
7 GethDebugTracerType, GethDebugTracingCallOptions, GethDebugTracingOptions, GethTrace,
8 PreStateFrame, PreStateMode,
9 },
10};
11use polkadot_sdk::{
12 pallet_revive::evm::{
13 self, AccessListEntry, AddressOrAddresses, AuthorizationListEntry, BlockNumberOrTagOrHash,
14 BlockTag, Byte, Bytes, CallLog, CallTrace, CallTracerConfig, Filter, FilterTopic,
15 FilterTopics, GenericTransaction, InputOrData, PrestateTrace, PrestateTraceInfo,
16 PrestateTracerConfig, Trace, TracerType,
17 },
18 sp_core,
19};
20use serde::{Deserialize, Serialize};
21use subxt::utils::{H160, H256};
22
23#[derive(Debug, Clone, Copy, PartialEq, Eq)]
24pub struct AlloyU256(alloy_primitives::U256);
25
26impl From<polkadot_sdk::sp_core::U256> for AlloyU256 {
27 fn from(value: polkadot_sdk::sp_core::U256) -> Self {
28 let mut bytes = [0u8; 32];
29 value.write_as_big_endian(&mut bytes);
30 Self(alloy_primitives::U256::from_be_bytes(bytes))
31 }
32}
33
34impl AlloyU256 {
35 pub fn inner(&self) -> alloy_primitives::U256 {
36 self.0
37 }
38}
39
40#[derive(Debug, Clone, Copy, PartialEq, Eq)]
41pub struct SubstrateU256(sp_core::U256);
42
43impl From<alloy_primitives::U256> for SubstrateU256 {
44 fn from(value: alloy_primitives::U256) -> Self {
45 Self(sp_core::U256::from_big_endian(&value.to_be_bytes::<32>()))
46 }
47}
48
49impl SubstrateU256 {
50 pub fn inner(&self) -> sp_core::U256 {
51 self.0
52 }
53}
54
55#[derive(Debug, Clone, Copy, PartialEq, Eq)]
56pub struct ReviveAddress(H160);
57
58impl ReviveAddress {
59 pub fn new(addr: H160) -> Self {
60 Self(addr)
61 }
62
63 pub fn inner(&self) -> H160 {
64 self.0
65 }
66}
67
68impl From<Address> for ReviveAddress {
69 fn from(addr: Address) -> Self {
70 Self(H160::from_slice(addr.0.as_ref()))
71 }
72}
73
74impl From<ReviveAddress> for Address {
75 fn from(value: ReviveAddress) -> Self {
76 Self(alloy_primitives::U160::from_be_bytes(*value.0.as_fixed_bytes()).into())
77 }
78}
79
80pub struct ReviveBlockNumberOrTag(pub evm::BlockNumberOrTag);
81
82impl From<BlockNumberOrTag> for ReviveBlockNumberOrTag {
83 fn from(value: BlockNumberOrTag) -> Self {
84 Self(match value {
85 BlockNumberOrTag::Latest => evm::BlockNumberOrTag::BlockTag(BlockTag::Latest),
86 BlockNumberOrTag::Finalized => evm::BlockNumberOrTag::BlockTag(BlockTag::Finalized),
87 BlockNumberOrTag::Safe => evm::BlockNumberOrTag::BlockTag(BlockTag::Safe),
88 BlockNumberOrTag::Earliest => evm::BlockNumberOrTag::BlockTag(BlockTag::Earliest),
89 BlockNumberOrTag::Pending => evm::BlockNumberOrTag::BlockTag(BlockTag::Pending),
90 BlockNumberOrTag::Number(num) => evm::BlockNumberOrTag::U256(evm::U256::from(num)),
91 })
92 }
93}
94
95impl ReviveBlockNumberOrTag {
96 pub fn inner(self) -> evm::BlockNumberOrTag {
97 self.0
98 }
99}
100
101#[derive(Debug, Clone)]
102pub struct ReviveBlockId(BlockNumberOrTagOrHash);
103
104impl ReviveBlockId {
105 pub fn inner(self) -> BlockNumberOrTagOrHash {
106 self.0
107 }
108}
109
110impl From<Option<BlockId>> for ReviveBlockId {
111 fn from(block_id: Option<BlockId>) -> Self {
112 Self(block_id.map_or(
113 BlockNumberOrTagOrHash::BlockTag(BlockTag::Latest),
114 |b_id| match b_id {
115 BlockId::Hash(rpc_hash) => BlockNumberOrTagOrHash::BlockHash(H256::from_slice(
116 rpc_hash.block_hash.as_slice(),
117 )),
118 BlockId::Number(number_or_tag) => {
119 ReviveBlockNumberOrTag::from(number_or_tag).inner().into()
120 }
121 },
122 ))
123 }
124}
125
126#[derive(Debug, Clone)]
127pub struct ReviveAccessList(Vec<AccessListEntry>);
128
129impl ReviveAccessList {
130 pub fn inner(self) -> Vec<AccessListEntry> {
131 self.0
132 }
133}
134
135impl From<AccessList> for ReviveAccessList {
136 fn from(value: AccessList) -> Self {
137 Self(
138 value
139 .0
140 .into_iter()
141 .map(|access_list_entry| AccessListEntry {
142 address: ReviveAddress::from(access_list_entry.address).inner(),
143 storage_keys: access_list_entry
144 .storage_keys
145 .into_iter()
146 .map(|key| H256::from_slice(key.as_ref()))
147 .collect(),
148 })
149 .collect(),
150 )
151 }
152}
153
154#[derive(Debug, Clone)]
155pub struct ReviveAuthorizationListEntry(AuthorizationListEntry);
156
157impl ReviveAuthorizationListEntry {
158 pub fn inner(self) -> AuthorizationListEntry {
159 self.0
160 }
161}
162
163impl From<SignedAuthorization> for ReviveAuthorizationListEntry {
164 fn from(value: SignedAuthorization) -> Self {
165 Self(AuthorizationListEntry {
166 chain_id: SubstrateU256::from(value.inner().chain_id).inner(),
167 address: ReviveAddress::from(value.inner().address).inner(),
168 nonce: value.inner().nonce.into(),
169 y_parity: value.y_parity().into(),
170 r: SubstrateU256::from(value.r()).inner(),
171 s: SubstrateU256::from(value.s()).inner(),
172 })
173 }
174}
175
176#[derive(Debug, Clone)]
177pub struct ReviveBytes(Bytes);
178
179impl From<alloy_primitives::Bytes> for ReviveBytes {
180 fn from(value: alloy_primitives::Bytes) -> Self {
181 Self(Bytes::from(value.to_vec()))
182 }
183}
184
185impl ReviveBytes {
186 pub fn inner(self) -> Bytes {
187 self.0
188 }
189}
190
191pub(crate) fn convert_to_generic_transaction(
192 transaction_request: TransactionRequest,
193) -> GenericTransaction {
194 GenericTransaction {
195 access_list: transaction_request
196 .access_list
197 .map(|access_list| ReviveAccessList::from(access_list).inner()),
198 authorization_list: transaction_request.authorization_list.map_or(
199 Default::default(),
200 |authorization_list| {
201 authorization_list
202 .into_iter()
203 .map(|entry| ReviveAuthorizationListEntry::from(entry).inner())
204 .collect()
205 },
206 ),
207 blob_versioned_hashes: transaction_request
208 .blob_versioned_hashes
209 .unwrap_or_default()
210 .into_iter()
211 .map(|b256| H256::from_slice(b256.as_ref()))
212 .collect(),
213 blobs: transaction_request
214 .sidecar
215 .unwrap_or_default()
216 .blobs
217 .into_iter()
218 .map(|blob| Bytes::from(blob.0.to_vec()))
219 .collect(),
220 chain_id: transaction_request.chain_id.map(sp_core::U256::from),
221 from: transaction_request.from.map(|addr| ReviveAddress::from(addr).inner()),
222 gas: transaction_request.gas.map(sp_core::U256::from),
223 gas_price: transaction_request.gas_price.map(sp_core::U256::from),
224 input: InputOrData::from(
225 ReviveBytes::from(transaction_request.input.into_input().unwrap_or_default()).inner(),
226 ),
227 max_fee_per_blob_gas: transaction_request.max_fee_per_blob_gas.map(sp_core::U256::from),
228 max_fee_per_gas: transaction_request.max_fee_per_gas.map(sp_core::U256::from),
229 max_priority_fee_per_gas: transaction_request
230 .max_priority_fee_per_gas
231 .map(sp_core::U256::from),
232 nonce: transaction_request.nonce.map(sp_core::U256::from),
233 to: transaction_request
234 .to
235 .and_then(|tx_kind| tx_kind.into_to())
236 .map(|addr| ReviveAddress::from(addr).inner()),
237 r#type: transaction_request.transaction_type.map(Byte::from),
238 value: transaction_request.value.map(|value| SubstrateU256::from(value).inner()),
239 }
240}
241
242struct ReviveFilterTopics(FilterTopics);
243
244impl ReviveFilterTopics {
245 fn into_inner(self) -> FilterTopics {
246 self.0
247 }
248}
249
250impl From<[Topic; 4]> for ReviveFilterTopics {
251 fn from(value: [Topic; 4]) -> Self {
252 let topics: Vec<FilterTopic> = value
253 .into_iter()
254 .filter(|t| !t.is_empty())
255 .map(|topic| {
256 let hashes: Vec<H256> =
257 topic.into_iter().map(|hash| H256::from_slice(hash.as_ref())).collect();
258 match hashes.len() {
259 1 => FilterTopic::Single(hashes[0]),
260 _ => FilterTopic::Multiple(hashes),
261 }
262 })
263 .collect();
264 Self(topics)
265 }
266}
267
268struct ReviveAddressOrAddresses(AddressOrAddresses);
269
270impl ReviveAddressOrAddresses {
271 fn into_inner(self) -> AddressOrAddresses {
272 self.0
273 }
274}
275
276impl From<FilterSet<Address>> for ReviveAddressOrAddresses {
277 fn from(value: FilterSet<Address>) -> Self {
278 let addresses: Vec<Address> = value.into_iter().collect();
279 let address_or_addresses = match addresses.len() {
280 0 => AddressOrAddresses::Address(Default::default()),
281 1 => AddressOrAddresses::Address(ReviveAddress::from(addresses[0]).inner()),
282 _ => AddressOrAddresses::Addresses(
283 addresses.into_iter().map(|address| ReviveAddress::from(address).inner()).collect(),
284 ),
285 };
286 Self(address_or_addresses)
287 }
288}
289
290pub struct ReviveFilter(Filter);
291
292impl ReviveFilter {
293 pub fn into_inner(self) -> Filter {
294 self.0
295 }
296}
297
298impl From<alloy_rpc_types::Filter> for ReviveFilter {
299 fn from(value: alloy_rpc_types::Filter) -> Self {
300 let address = if value.address.is_empty() {
301 None
302 } else {
303 Some(ReviveAddressOrAddresses::from(value.address).into_inner())
304 };
305 let topics = if value.topics.iter().all(|t| t.is_empty()) {
306 None
307 } else {
308 Some(ReviveFilterTopics::from(value.topics).into_inner())
309 };
310 let (from_block, to_block, block_hash) = match value.block_option {
311 FilterBlockOption::Range { from_block, to_block } => (
312 from_block.map(|fb| ReviveBlockNumberOrTag::from(fb).inner()),
313 to_block.map(|tb| ReviveBlockNumberOrTag::from(tb).inner()),
314 None,
315 ),
316 FilterBlockOption::AtBlockHash(hash) => {
317 (None, None, Some(H256::from_slice(hash.as_ref())))
318 }
319 };
320 Self(Filter { address, from_block, to_block, block_hash, topics })
321 }
322}
323
324#[derive(Debug, Clone, PartialEq)]
325pub struct ReviveTracerType(TracerType);
326
327impl ReviveTracerType {
328 pub fn new(tracer_type: TracerType) -> Self {
329 Self(tracer_type)
330 }
331
332 pub fn inner(self) -> TracerType {
333 self.0
334 }
335}
336
337impl From<GethDebugTracingOptions> for ReviveTracerType {
338 fn from(tracing_options: GethDebugTracingOptions) -> Self {
339 let tracer_type = if let Some(GethDebugTracerType::BuiltInTracer(geth_tracer_type)) =
340 tracing_options.tracer
341 {
342 match geth_tracer_type {
343 GethDebugBuiltInTracerType::CallTracer => {
344 TracerType::CallTracer(Some(CallTracerConfig::default()))
345 }
346 GethDebugBuiltInTracerType::PreStateTracer => {
347 let mut prestate_config = PrestateTracerConfig::default();
348 if tracing_options.config.disable_storage.unwrap_or(false) {
349 prestate_config.disable_storage = true;
350 }
351 TracerType::PrestateTracer(Some(prestate_config))
352 }
353 _ => Default::default(),
354 }
355 } else {
356 Default::default()
357 };
358 Self(tracer_type)
359 }
360}
361
362impl From<GethDebugTracingCallOptions> for ReviveTracerType {
363 fn from(tracing_call_options: GethDebugTracingCallOptions) -> Self {
364 Self::from(tracing_call_options.tracing_options)
365 }
366}
367
368#[derive(Debug, Default, Clone, Serialize, Deserialize, Eq, PartialEq)]
369pub struct ReviveCallLog(CallLog);
370
371impl ReviveCallLog {
372 pub fn new(call_log: CallLog) -> Self {
373 Self(call_log)
374 }
375
376 pub fn inner(self) -> CallLog {
377 self.0
378 }
379}
380
381impl From<ReviveCallLog> for CallLogFrame {
382 fn from(value: ReviveCallLog) -> Self {
383 let call_log = value.inner();
384 Self {
385 address: Some(Address::from_slice(call_log.address.as_ref())),
386 topics: Some(
387 call_log.topics.into_iter().map(|topic| B256::from_slice(topic.as_ref())).collect(),
388 ),
389 data: Some(call_log.data.0.into()),
390 position: Some(call_log.position.into()),
391 index: None,
393 }
394 }
395}
396
397#[derive(Default, Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
398pub struct RevivePrestateTraceInfo(PrestateTraceInfo);
399
400impl RevivePrestateTraceInfo {
401 pub fn new(prestate_trace_info: PrestateTraceInfo) -> Self {
402 Self(prestate_trace_info)
403 }
404
405 pub fn inner(self) -> PrestateTraceInfo {
406 self.0
407 }
408}
409
410impl From<RevivePrestateTraceInfo> for AccountState {
411 fn from(value: RevivePrestateTraceInfo) -> Self {
412 let prestate_trace_info = value.inner();
413 Self {
414 balance: prestate_trace_info.balance.map(|b| AlloyU256::from(b).inner()),
415 code: prestate_trace_info.code.map(|c| c.0.into()),
416 nonce: prestate_trace_info.nonce.map(|n| n.into()),
417 storage: prestate_trace_info
418 .storage
419 .into_iter()
420 .map(|(k, v)| {
421 (
422 B256::from_slice(k.0.as_slice()),
423 B256::from_slice(v.unwrap_or(Bytes(vec![0u8; 32])).0.as_slice()),
424 )
425 })
426 .collect(),
427 }
428 }
429}
430
431#[derive(Deserialize, Serialize, Clone, Debug, Eq, PartialEq)]
432pub struct ReviveCallTrace(CallTrace);
433
434impl ReviveCallTrace {
435 pub fn new(call_trace: CallTrace) -> Self {
436 Self(call_trace)
437 }
438
439 pub fn inner(self) -> CallTrace {
440 self.0
441 }
442}
443
444impl From<ReviveCallTrace> for CallFrame {
445 fn from(value: ReviveCallTrace) -> Self {
446 let call_trace = value.inner();
447 Self {
448 from: Address::from_slice(call_trace.from.as_ref()),
449 gas: AlloyU256::from(call_trace.gas).inner(),
450 gas_used: AlloyU256::from(call_trace.gas_used).inner(),
451 to: Some(Address::from_slice(call_trace.to.as_ref())),
452 input: call_trace.input.0.into(),
453 output: Some(call_trace.output.0.into()),
454 error: call_trace.error,
455 revert_reason: call_trace.revert_reason,
456 calls: call_trace
457 .calls
458 .into_iter()
459 .map(|c_t| ReviveCallTrace::new(c_t).into())
460 .collect(),
461 logs: call_trace.logs.into_iter().map(|c_l| ReviveCallLog::new(c_l).into()).collect(),
462 value: call_trace.value.map(|v| AlloyU256::from(v).inner()),
463 typ: serde_json::to_string(&call_trace.call_type)
464 .unwrap()
465 .trim_matches('"')
466 .to_string(),
467 }
468 }
469}
470
471#[derive(Deserialize, Serialize, Clone, Debug, Eq, PartialEq)]
472pub struct ReviveTrace(Trace);
473
474impl ReviveTrace {
475 pub fn new(trace: Trace) -> Self {
476 Self(trace)
477 }
478
479 pub fn inner(self) -> Trace {
480 self.0
481 }
482}
483
484impl From<ReviveTrace> for GethTrace {
485 fn from(value: ReviveTrace) -> Self {
486 match value.inner() {
487 Trace::Call(call_trace) => Self::CallTracer(ReviveCallTrace::new(call_trace).into()),
488 Trace::Prestate(PrestateTrace::Prestate(prestate_map)) => {
489 Self::PreStateTracer(PreStateFrame::Default(PreStateMode(
490 prestate_map
491 .into_iter()
492 .map(|(account_address, prestate_trace_info)| {
493 (
494 Address::from_slice(account_address.as_ref()),
495 RevivePrestateTraceInfo::new(prestate_trace_info).into(),
496 )
497 })
498 .collect(),
499 )))
500 }
501 Trace::Prestate(PrestateTrace::DiffMode { pre, post }) => {
502 Self::PreStateTracer(PreStateFrame::Diff(DiffMode {
503 pre: pre
504 .into_iter()
505 .map(|(account_address, prestate_trace_info)| {
506 (
507 Address::from_slice(account_address.as_ref()),
508 RevivePrestateTraceInfo::new(prestate_trace_info).into(),
509 )
510 })
511 .collect(),
512 post: post
513 .into_iter()
514 .map(|(account_address, prestate_trace_info)| {
515 (
516 Address::from_slice(account_address.as_ref()),
517 RevivePrestateTraceInfo::new(prestate_trace_info).into(),
518 )
519 })
520 .collect(),
521 }))
522 }
523 }
524 }
525}