casper_types/chainspec/
refund_handling.rs1use num_rational::Ratio;
4use num_traits::Zero;
5use serde::{Deserialize, Serialize};
6
7use crate::bytesrepr::{self, FromBytes, ToBytes};
8
9const REFUND_HANDLING_REFUND_TAG: u8 = 0;
10const REFUND_HANDLING_BURN_TAG: u8 = 1;
11const REFUND_HANDLING_NONE_TAG: u8 = 2;
12
13#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Default)]
15#[serde(tag = "type", rename_all = "snake_case")]
16pub enum RefundHandling {
17 Refund {
20 refund_ratio: Ratio<u64>,
28 },
29 Burn {
31 refund_ratio: Ratio<u64>,
34 },
35 #[default]
43 NoRefund,
44}
45
46impl RefundHandling {
47 pub fn skip_refund(&self) -> bool {
49 match self {
50 RefundHandling::NoRefund => true,
51 RefundHandling::Refund { refund_ratio } => refund_ratio.is_zero(),
52 RefundHandling::Burn { .. } => false,
53 }
54 }
55
56 pub fn refund_ratio(&self) -> Ratio<u64> {
58 match self {
59 RefundHandling::Refund { refund_ratio } | RefundHandling::Burn { refund_ratio } => {
60 *refund_ratio
61 }
62 RefundHandling::NoRefund => Ratio::zero(),
63 }
64 }
65}
66
67impl ToBytes for RefundHandling {
68 fn to_bytes(&self) -> Result<Vec<u8>, bytesrepr::Error> {
69 let mut buffer = bytesrepr::allocate_buffer(self)?;
70
71 match self {
72 RefundHandling::Refund { refund_ratio } => {
73 buffer.push(REFUND_HANDLING_REFUND_TAG);
74 buffer.extend(refund_ratio.to_bytes()?);
75 }
76 RefundHandling::Burn { refund_ratio } => {
77 buffer.push(REFUND_HANDLING_BURN_TAG);
78 buffer.extend(refund_ratio.to_bytes()?);
79 }
80 RefundHandling::NoRefund => {
81 buffer.push(REFUND_HANDLING_NONE_TAG);
82 }
83 }
84
85 Ok(buffer)
86 }
87
88 fn serialized_length(&self) -> usize {
89 1 + match self {
90 RefundHandling::Refund { refund_ratio } => refund_ratio.serialized_length(),
91 RefundHandling::Burn { refund_ratio } => refund_ratio.serialized_length(),
92 RefundHandling::NoRefund => 0,
93 }
94 }
95}
96
97impl FromBytes for RefundHandling {
98 fn from_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), bytesrepr::Error> {
99 let (tag, rem) = u8::from_bytes(bytes)?;
100 match tag {
101 REFUND_HANDLING_REFUND_TAG => {
102 let (refund_ratio, rem) = FromBytes::from_bytes(rem)?;
103 Ok((RefundHandling::Refund { refund_ratio }, rem))
104 }
105 REFUND_HANDLING_BURN_TAG => {
106 let (refund_ratio, rem) = FromBytes::from_bytes(rem)?;
107 Ok((RefundHandling::Burn { refund_ratio }, rem))
108 }
109 REFUND_HANDLING_NONE_TAG => Ok((RefundHandling::NoRefund, rem)),
110 _ => Err(bytesrepr::Error::Formatting),
111 }
112 }
113}
114
115#[cfg(test)]
116mod tests {
117 use super::*;
118
119 #[test]
120 fn bytesrepr_roundtrip_for_refund() {
121 let refund_config = RefundHandling::Refund {
122 refund_ratio: Ratio::new(49, 313),
123 };
124 bytesrepr::test_serialization_roundtrip(&refund_config);
125 }
126
127 #[test]
128 fn bytesrepr_roundtrip_for_burn() {
129 let refund_config = RefundHandling::Burn {
130 refund_ratio: Ratio::new(49, 313),
131 };
132 bytesrepr::test_serialization_roundtrip(&refund_config);
133 }
134
135 #[test]
136 fn bytesrepr_roundtrip_for_no_refund() {
137 let refund_config = RefundHandling::NoRefund;
138 bytesrepr::test_serialization_roundtrip(&refund_config);
139 }
140}