stratus/eth/primitives/
log.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
use display_json::DebugAsJson;

use crate::alias::AlloyLog;
use crate::alias::RevmLog;
use crate::eth::primitives::Address;
use crate::eth::primitives::Bytes;
use crate::eth::primitives::LogTopic;

/// Log is an event emitted by the EVM during contract execution.
#[derive(DebugAsJson, Clone, Default, PartialEq, Eq, fake::Dummy, serde::Serialize, serde::Deserialize)]
pub struct Log {
    /// Address that emitted the log.
    pub address: Address,

    /// Topics (0 to 4 positions) describing the log.
    pub topic0: Option<LogTopic>,
    pub topic1: Option<LogTopic>,
    pub topic2: Option<LogTopic>,
    pub topic3: Option<LogTopic>,

    /// Additional data.
    pub data: Bytes,
}

impl Log {
    /// Returns all topics in the log.
    pub fn topics(&self) -> [Option<LogTopic>; 4] {
        [self.topic0, self.topic1, self.topic2, self.topic3]
    }

    /// Returns all non-empty topics in the log.
    pub fn topics_non_empty(&self) -> Vec<LogTopic> {
        self.topics().into_iter().flatten().collect()
    }
}

// -----------------------------------------------------------------------------
// Conversions: Other -> Self
// ----------------------------------------------------------------------------
impl From<RevmLog> for Log {
    fn from(value: RevmLog) -> Self {
        let (topics, data) = value.data.split();
        let topics_len = topics.len();

        let mut log = Self {
            address: value.address.into(),
            data: data.into(),
            ..Default::default()
        };

        // you may not like it but this is what peak performance looks like
        match topics_len {
            4 => {
                log.topic0 = Some(topics[0].into());
                log.topic1 = Some(topics[1].into());
                log.topic2 = Some(topics[2].into());
                log.topic3 = Some(topics[3].into());
            }
            3 => {
                log.topic0 = Some(topics[0].into());
                log.topic1 = Some(topics[1].into());
                log.topic2 = Some(topics[2].into());
            }
            2 => {
                log.topic0 = Some(topics[0].into());
                log.topic1 = Some(topics[1].into());
            }
            1 => {
                log.topic0 = Some(topics[0].into());
            }
            _ => {}
        }

        log
    }
}

impl From<AlloyLog> for Log {
    fn from(value: AlloyLog) -> Self {
        let topics = value.inner.topics().to_vec();
        let topics_len = topics.len();

        let mut log = Self {
            address: value.inner.address.into(),
            data: value.inner.data.data.into(),
            ..Default::default()
        };

        // you may not like it but this is what peak performance looks like
        match topics_len {
            4 => {
                log.topic0 = Some(topics[0].into());
                log.topic1 = Some(topics[1].into());
                log.topic2 = Some(topics[2].into());
                log.topic3 = Some(topics[3].into());
            }
            3 => {
                log.topic0 = Some(topics[0].into());
                log.topic1 = Some(topics[1].into());
                log.topic2 = Some(topics[2].into());
            }
            2 => {
                log.topic0 = Some(topics[0].into());
                log.topic1 = Some(topics[1].into());
            }
            1 => {
                log.topic0 = Some(topics[0].into());
            }
            _ => {}
        }

        log
    }
}