1use crate::MtEvent;
2use defuse_near_utils::REFUND_MEMO;
3use near_sdk::FunctionError;
4
5#[derive(Debug, Clone, PartialEq, Eq, FunctionError, thiserror::Error)]
6#[error("refund event log would be too long")]
7pub struct ErrorLogTooLong;
8
9const REFUND_STR_LEN: usize = REFUND_MEMO.len();
10pub const REFUND_EXTRA_BYTES: usize = r#","memo":""#.len() + REFUND_STR_LEN;
11
12#[derive(Default, Clone, Copy)]
13#[must_use]
14pub struct RefundLogDelta {
15 overhead: usize,
16 savings: usize,
17}
18
19impl RefundLogDelta {
20 pub const fn new(overhead: usize, savings: usize) -> Self {
21 Self {
22 overhead: overhead.saturating_sub(savings),
23 savings: savings.saturating_sub(overhead),
24 }
25 }
26
27 pub const fn overhead(&self) -> usize {
28 self.overhead
29 }
30
31 pub const fn savings(&self) -> usize {
32 self.savings
33 }
34
35 pub const fn saturating_add(self, other: Self) -> Self {
36 Self::new(
37 self.overhead.saturating_add(other.overhead),
38 self.savings.saturating_add(other.savings),
39 )
40 }
41}
42
43const fn refund_log_delta(memo: Option<&str>) -> RefundLogDelta {
44 let Some(m) = memo else {
45 return RefundLogDelta {
46 overhead: REFUND_EXTRA_BYTES,
47 savings: 0,
48 };
49 };
50 RefundLogDelta::new(REFUND_STR_LEN, m.len())
51}
52
53impl MtEvent<'_> {
54 pub(crate) fn compute_refund_delta(&self) -> RefundLogDelta {
55 match self {
56 MtEvent::MtMint(events) => events
57 .iter()
58 .map(|e| refund_log_delta(e.memo.as_deref()))
59 .fold(RefundLogDelta::default(), RefundLogDelta::saturating_add),
60 MtEvent::MtBurn(events) => events
61 .iter()
62 .map(|e| refund_log_delta(e.memo.as_deref()))
63 .fold(RefundLogDelta::default(), RefundLogDelta::saturating_add),
64 MtEvent::MtTransfer(events) => events
65 .iter()
66 .map(|e| refund_log_delta(e.memo.as_deref()))
67 .fold(RefundLogDelta::default(), RefundLogDelta::saturating_add),
68 }
69 }
70}
71
72#[derive(Debug)]
75#[must_use = "call `.emit()` to emit the event"]
76pub struct CheckedMtEvent(pub(crate) String);
77
78impl CheckedMtEvent {
79 pub fn emit(self) {
80 near_sdk::env::log_str(&self.0);
81 }
82}
83
84#[cfg(test)]
85mod test {
86 use crate::checked::REFUND_EXTRA_BYTES;
87
88 use super::refund_log_delta;
89
90 #[test]
91 fn test_refund_log_delta_shorter_memo() {
92 let delta = refund_log_delta(Some("r"));
93 assert_eq!(delta.savings(), 0);
94 assert_eq!(delta.overhead(), 5);
95 }
96
97 #[test]
98 fn test_refund_log_delta_longer_memo() {
99 let delta = refund_log_delta(Some("refund123"));
100 assert_eq!(delta.savings(), 3);
101 assert_eq!(delta.overhead(), 0);
102 }
103
104 #[test]
105 fn test_refund_log_delta_equal_memo() {
106 let delta = refund_log_delta(Some("123456"));
107 assert_eq!(delta.savings(), 0);
108 assert_eq!(delta.overhead(), 0);
109 }
110
111 #[test]
112 fn test_refund_log_delta_empty_memo() {
113 let delta = refund_log_delta(None);
114 assert_eq!(delta.savings(), 0);
115 assert_eq!(delta.overhead(), REFUND_EXTRA_BYTES);
116 }
117}