Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ impl Encode for DistributionFunction {
n,
o,
start_moment: s,
c,
b,
min_value,
max_value,
} => {
Expand All @@ -98,7 +98,7 @@ impl Encode for DistributionFunction {
n.encode(encoder)?;
o.encode(encoder)?;
s.encode(encoder)?;
c.encode(encoder)?;
b.encode(encoder)?;
min_value.encode(encoder)?;
max_value.encode(encoder)?;
}
Expand Down Expand Up @@ -234,8 +234,8 @@ impl Decode for DistributionFunction {
let m = i64::decode(decoder)?;
let n = u64::decode(decoder)?;
let o = i64::decode(decoder)?;
let s = Option::<u64>::decode(decoder)?;
let c = TokenAmount::decode(decoder)?;
let start_moment = Option::<u64>::decode(decoder)?;
let b = TokenAmount::decode(decoder)?;
let min_value = Option::<u64>::decode(decoder)?;
let max_value = Option::<u64>::decode(decoder)?;
Ok(Self::Exponential {
Expand All @@ -244,8 +244,8 @@ impl Decode for DistributionFunction {
m,
n,
o,
start_moment: s,
c,
start_moment,
b,
min_value,
max_value,
})
Expand Down Expand Up @@ -384,8 +384,8 @@ impl<'de> BorrowDecode<'de> for DistributionFunction {
let m = i64::borrow_decode(decoder)?;
let n = u64::borrow_decode(decoder)?;
let o = i64::borrow_decode(decoder)?;
let s = Option::<u64>::borrow_decode(decoder)?;
let c = TokenAmount::borrow_decode(decoder)?;
let start_moment = Option::<u64>::borrow_decode(decoder)?;
let b = TokenAmount::borrow_decode(decoder)?;
let min_value = Option::<u64>::borrow_decode(decoder)?;
let max_value = Option::<u64>::borrow_decode(decoder)?;
Ok(Self::Exponential {
Expand All @@ -394,8 +394,8 @@ impl<'de> BorrowDecode<'de> for DistributionFunction {
m,
n,
o,
start_moment: s,
c,
start_moment,
b,
min_value,
max_value,
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ impl DistributionFunction {
n,
o,
start_moment,
c,
b,
min_value,
max_value,
} => {
Expand Down Expand Up @@ -284,7 +284,7 @@ impl DistributionFunction {
}

let exponent = (*m as f64) * (diff as f64) / (*n as f64);
let value = ((*a as f64) * exponent.exp() / (*d as f64)) + (*c as f64);
let value = ((*a as f64) * exponent.exp() / (*d as f64)) + (*b as f64);
if let Some(max_value) = max_value {
if value.is_infinite() && value.is_sign_positive() || value > *max_value as f64
{
Expand Down Expand Up @@ -346,22 +346,73 @@ impl DistributionFunction {
return Err(ProtocolError::Overflow("Logarithmic function: argument for log is too big (max should be u64::MAX)"));
}

let argument = (*m as f64) * (diff as f64) / (*n as f64);
let argument = if *m == 1 {
if *n == 1 {
diff as f64
} else {
(diff as f64) / (*n as f64)
}
} else if *n == 1 {
(*m as f64) * (diff as f64)
} else {
(*m as f64) * (diff as f64) / (*n as f64)
};

let log_val = argument.ln();
let value = ((*a as f64) * log_val / (*d as f64)) + (*b as f64);
if let Some(max_value) = max_value {
if value.is_infinite() && value.is_sign_positive() || value > *max_value as f64
{
return Ok(*max_value);
}
}
if !value.is_finite() || value > (u64::MAX as f64) {

// Ensure the computed value is finite and within the u64 range.
if !log_val.is_finite() || log_val > (u64::MAX as f64) {
return Err(ProtocolError::Overflow(
"Logarithmic function evaluation overflow or negative",
"InvertedLogarithmic: evaluation overflow",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Likely incorrect error label.

This line uses "InvertedLogarithmic: evaluation overflow" within the Logarithmic variant. The error message label seems mismatched and could confuse users.

- "InvertedLogarithmic: evaluation overflow",
+ "Logarithmic: evaluation overflow",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"InvertedLogarithmic: evaluation overflow",
"Logarithmic: evaluation overflow",

));
}
if value < 0.0 {

let intermediate = if *a == 1 {
log_val
} else if *a == -1 {
-log_val
} else {
(*a as f64) * log_val
};

let value = if d == &1 {
if !intermediate.is_finite() || intermediate > (i64::MAX as f64) {
if let Some(max_value) = max_value {
if intermediate.is_sign_positive() {
*max_value as i64
} else {
return Err(ProtocolError::Overflow(
"InvertedLogarithmic: evaluation overflow intermediate bigger than i64::max",
));
}
Comment on lines +370 to +387
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Additional mismatch in error messages.

Throughout this block, references to "InvertedLogarithmic" appear inside Logarithmic logic. This likely results from copy-paste. Updating them to "Logarithmic" will improve clarity and correctness.

} else {
return Err(ProtocolError::Overflow(
"InvertedLogarithmic: evaluation overflow intermediate bigger than i64::max",
));
}
} else {
(intermediate.floor() as i64)
.checked_add(*b as i64)
.or(max_value.map(|max| max as i64))
.ok_or(ProtocolError::Overflow(
"InvertedLogarithmic: evaluation overflow when adding b",
))?
}
} else {
if !intermediate.is_finite() || intermediate > (i64::MAX as f64) {
return Err(ProtocolError::Overflow(
"InvertedLogarithmic: evaluation overflow intermediate bigger than i64::max",
));
}
((intermediate / (*d as f64)).floor() as i64)
.checked_add(*b as i64)
.or(max_value.map(|max| max as i64))
.ok_or(ProtocolError::Overflow(
"InvertedLogarithmic: evaluation overflow when adding b",
))?
};

if value < 0 {
return if let Some(min_value) = min_value {
Ok(*min_value)
} else {
Expand All @@ -374,6 +425,12 @@ impl DistributionFunction {
return Ok(*min_value);
}
}

if let Some(max_value) = max_value {
if value_u64 > *max_value {
return Ok(*max_value);
}
}
Ok(value_u64)
}
DistributionFunction::InvertedLogarithmic {
Expand Down Expand Up @@ -900,7 +957,7 @@ mod tests {
n: 1,
o: 0,
start_moment: Some(0),
c: 10,
b: 10,
min_value: None,
max_value: None,
};
Expand All @@ -918,7 +975,7 @@ mod tests {
n: 1,
o: 0,
start_moment: Some(0),
c: 10,
b: 10,
min_value: None,
max_value: None,
};
Expand All @@ -938,7 +995,7 @@ mod tests {
n: 1,
o: 0,
start_moment: Some(0),
c: 5,
b: 5,
min_value: None,
max_value: None,
};
Expand All @@ -957,7 +1014,7 @@ mod tests {
n: 10,
o: 0,
start_moment: Some(0),
c: 0,
b: 0,
min_value: None,
max_value: None,
};
Expand All @@ -976,7 +1033,7 @@ mod tests {
n: 1,
o: 0,
start_moment: Some(0),
c: 0,
b: 0,
min_value: None,
max_value: Some(100000000),
};
Expand All @@ -997,7 +1054,7 @@ mod tests {
n: 1,
o: 0,
start_moment: Some(0),
c: 10,
b: 10,
min_value: None,
max_value: None,
};
Expand All @@ -1016,7 +1073,7 @@ mod tests {
n: 1,
o: 0,
start_moment: Some(0),
c: 10,
b: 10,
min_value: Some(11),
max_value: None,
};
Expand All @@ -1035,7 +1092,7 @@ mod tests {
n: 2,
o: 0,
start_moment: Some(0),
c: 10,
b: 10,
min_value: Some(1),
max_value: Some(11), // Set max at the starting value
};
Expand All @@ -1061,7 +1118,7 @@ mod tests {
n: 10,
o: 0,
start_moment: Some(0),
c: 5,
b: 5,
min_value: None,
max_value: None,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ pub enum DistributionFunction {
/// The emission at period `x` is given by:
///
/// ```text
/// f(x) = (a * e^(m * (x - s) / n)) / d + c
/// f(x) = (a * e^(m * (x - s) / n)) / d + b
/// ```
///
/// # Parameters
Expand All @@ -364,7 +364,7 @@ pub enum DistributionFunction {
/// - `d`: A divisor used to scale the exponential term.
/// - `s`: Optional start period offset. If not set, the contract creation start is assumed.
/// - `o`: An offset for the exp function, this is useful if s is in None.
/// - `c`: An offset added to the result.
/// - `b`: An offset added to the result.
/// - `min_value` / `max_value`: Optional constraints on the emitted tokens.
///
/// # Use Cases
Expand All @@ -390,7 +390,7 @@ pub enum DistributionFunction {
///
/// ## **Example 2: Exponential Decay (`m < 0`)**
/// - **Use Case**: A deflationary model where emissions start high and gradually decrease to ensure scarcity.
/// - **Parameters**: `a = 500`, `m = -3`, `n = 100`, `d = 20`, `c = 10`
/// - **Parameters**: `a = 500`, `m = -3`, `n = 100`, `d = 20`, `b = 10`
/// - **Formula**:
/// ```text
/// f(x) = (500 * e^(-3 * (x - s) / 100)) / 20 + 10
Expand All @@ -403,12 +403,12 @@ pub enum DistributionFunction {
n: u64,
o: i64,
start_moment: Option<u64>,
c: TokenAmount,
b: TokenAmount,
min_value: Option<u64>,
max_value: Option<u64>,
},

/// Emits tokens following a logarithmic function.
/// Emits tokens following a natural logarithmic (ln) function.
///
/// # Formula
/// The emission at period `x` is computed as:
Expand Down Expand Up @@ -440,7 +440,7 @@ pub enum DistributionFunction {
///
/// - Given the formula:
/// ```text
/// f(x) = (a * log(m * (x - s + o) / n)) / d + b
/// f(x) = (a * ln(m * (x - s + o) / n)) / d + b
/// ```
///
/// - Let’s assume the following parameters:
Expand All @@ -452,7 +452,7 @@ pub enum DistributionFunction {
///
/// - This results in:
/// ```text
/// f(x) = (100 * log(2 * (x + 1) / 1)) / 10 + 50
/// f(x) = (100 * ln(2 * (x + 1) / 1)) / 10 + 50
/// ```
///
/// - **Expected Behavior:**
Expand All @@ -476,13 +476,13 @@ pub enum DistributionFunction {
min_value: Option<u64>,
max_value: Option<u64>,
},
/// Emits tokens following an inverted logarithmic function.
/// Emits tokens following an inverted natural logarithmic function.
///
/// # Formula
/// The emission at period `x` is given by:
///
/// ```text
/// f(x) = (a * log( n / (m * (x - s + o)) )) / d + b
/// f(x) = (a * ln( n / (m * (x - s + o)) )) / d + b
/// ```
///
/// # Parameters
Expand All @@ -504,7 +504,7 @@ pub enum DistributionFunction {
///
/// # Example
/// ```text
/// f(x) = 10000 * log(5000 / x)
/// f(x) = 10000 * ln(5000 / x)
/// ```
/// - Values: a = 10000 n = 5000 m = 1 o = 0 b = 0 d = 0
/// y
Expand Down Expand Up @@ -651,18 +651,18 @@ impl fmt::Display for DistributionFunction {
m,
n,
o,
start_moment: s,
c,
start_moment,
b,
min_value,
max_value,
} => {
write!(f, "Exponential: f(x) = {} * e^( {} * (x", a, m)?;
if let Some(start) = s {
if let Some(start) = start_moment {
write!(f, " - {} + {})", start, o)?;
} else {
write!(f, " + {})", o)?;
}
write!(f, " / {} ) / {} + {}", n, d, c)?;
write!(f, " / {} ) / {} + {}", n, d, b)?;
if let Some(min) = min_value {
write!(f, ", min: {}", min)?;
}
Expand Down
Loading