cfx_execute_helper/phantom_tx/
recover.rs1use cfx_executor::internal_contract::{
2 cross_space_events::*, SolidityEventTrait,
3};
4use cfx_parameters::internal_contract_addresses::CROSS_SPACE_CONTRACT_ADDRESS;
5use cfx_types::{Address, Bloom, Space, H256, U256};
6use primitives::{log_entry::build_bloom, Action, LogEntry, TransactionStatus};
7use solidity_abi::{ABIDecodable, ABIEncodable};
8
9use super::PhantomTransaction;
10
11type Bytes20 = [u8; 20];
12
13pub fn build_bloom_and_recover_phantom(
14 logs: &[LogEntry], tx_hash: H256,
15) -> (Vec<PhantomTransaction>, Bloom) {
16 (recover_phantom(logs, tx_hash), build_bloom(logs))
17}
18
19pub fn recover_phantom(
20 logs: &[LogEntry], tx_hash: H256,
21) -> Vec<PhantomTransaction> {
22 let mut phantom_txs: Vec<PhantomTransaction> = Default::default();
23 let mut maybe_working_tx: Option<PhantomTransaction> = None;
24 let mut cross_space_nonce = 0u32;
25 for log in logs.iter() {
26 if log.address == CROSS_SPACE_CONTRACT_ADDRESS {
27 let event_sig = log.topics.first().unwrap();
28 if event_sig == &CallEvent::EVENT_SIG
29 || event_sig == &CreateEvent::EVENT_SIG
30 {
31 assert!(maybe_working_tx.is_none());
32
33 let from = Address::from(
34 Bytes20::abi_decode(&log.topics[1].as_ref()).unwrap(),
35 );
36 let to = Address::from(
37 Bytes20::abi_decode(&log.topics[2].as_ref()).unwrap(),
38 );
39 let (value, nonce, data): (_, _, Vec<u8>) =
40 ABIDecodable::abi_decode(&log.data).unwrap();
41
42 let is_create = event_sig == &CreateEvent::EVENT_SIG;
43 let action = if is_create {
44 Action::Create
45 } else {
46 Action::Call(to)
47 };
48 phantom_txs.push(PhantomTransaction::simple_transfer(
52 Address::zero(),
53 from,
54 U256::zero(), value,
56 (tx_hash, U256::from(cross_space_nonce)).abi_encode(),
58 ));
59 cross_space_nonce += 1;
60 maybe_working_tx = Some(PhantomTransaction {
64 from,
65 nonce,
66 action,
67 value,
68 data,
69 ..Default::default()
70 });
71 } else if event_sig == &WithdrawEvent::EVENT_SIG {
72 let from = Address::from(
73 Bytes20::abi_decode(&log.topics[1].as_ref()).unwrap(),
74 );
75 let (value, nonce) =
76 ABIDecodable::abi_decode(&log.data).unwrap();
77 phantom_txs.push(PhantomTransaction::simple_transfer(
79 from,
80 Address::zero(),
81 nonce,
82 value,
83 vec![],
84 ));
85 } else if event_sig == &ReturnEvent::EVENT_SIG {
86 let success: bool =
87 ABIDecodable::abi_decode(&log.data).unwrap();
88
89 let mut working_tx =
90 std::mem::take(&mut maybe_working_tx).unwrap();
91
92 working_tx.outcome_status = if success {
93 TransactionStatus::Success
94 } else {
95 TransactionStatus::Failure
96 };
97
98 phantom_txs.push(working_tx);
100 }
101 } else if log.space == Space::Ethereum {
102 if let Some(ref mut working_tx) = maybe_working_tx {
103 working_tx.logs.push(log.clone());
105 working_tx.log_bloom.accrue_bloom(&log.bloom());
106 } else {
107 }
110 }
111 }
112 return phantom_txs;
113}