use crate::{evm::fees::InfoT, BalanceOf, Config, StorageDeposit};
use frame_support::DebugNoBound;
use sp_core::Get;
use sp_runtime::{FixedPointNumber, Saturating};
#[derive(Clone, Eq, PartialEq, DebugNoBound)]
pub enum SignedGas<T: Config> {
Positive(BalanceOf<T>),
Negative(BalanceOf<T>),
}
use SignedGas::{Negative, Positive};
impl<T: Config> Default for SignedGas<T> {
fn default() -> Self {
Self::Positive(Default::default())
}
}
impl<T: Config> SignedGas<T> {
pub fn safe_new_negative(amount: BalanceOf<T>) -> Self {
if amount == Default::default() {
Positive(amount)
} else {
Negative(amount)
}
}
pub fn from_weight_fee(weight_fee: BalanceOf<T>) -> Self {
Self::Positive(weight_fee)
}
pub fn from_ethereum_gas(gas: BalanceOf<T>) -> Self {
let gas_scale = <T as Config>::GasScale::get();
Self::Positive(gas.saturating_mul(gas_scale.into()))
}
pub fn from_adjusted_deposit_charge(deposit: &StorageDeposit<BalanceOf<T>>) -> Self {
let multiplier = T::FeeInfo::next_fee_multiplier_reciprocal();
match deposit {
StorageDeposit::Charge(amount) => Positive(multiplier.saturating_mul_int(*amount)),
StorageDeposit::Refund(amount) =>
Self::safe_new_negative(multiplier.saturating_mul_int(*amount)),
}
}
pub fn to_weight_fee(&self) -> Option<BalanceOf<T>> {
match self {
Positive(amount) => Some(*amount),
Negative(..) => None,
}
}
pub fn to_ethereum_gas(&self) -> Option<BalanceOf<T>> {
let gas_scale: BalanceOf<T> = <T as Config>::GasScale::get().into();
match self {
Positive(amount) =>
Some((amount.saturating_add(gas_scale.saturating_sub(1u32.into()))) / gas_scale),
Negative(..) => None,
}
}
pub fn to_adjusted_deposit_charge(&self) -> Option<BalanceOf<T>> {
match self {
Positive(amount) => {
let multiplier = T::FeeInfo::next_fee_multiplier();
Some(multiplier.saturating_mul_int(*amount))
},
_ => None,
}
}
pub fn saturating_add(&self, rhs: &Self) -> Self {
match (self, rhs) {
(Positive(lhs), Positive(rhs)) => Positive(lhs.saturating_add(*rhs)),
(Negative(lhs), Negative(rhs)) => Self::safe_new_negative(lhs.saturating_add(*rhs)),
(Positive(lhs), Negative(rhs)) =>
if lhs >= rhs {
Positive(lhs.saturating_sub(*rhs))
} else {
Self::safe_new_negative(rhs.saturating_sub(*lhs))
},
(Negative(lhs), Positive(rhs)) =>
if lhs > rhs {
Self::safe_new_negative(lhs.saturating_sub(*rhs))
} else {
Positive(rhs.saturating_sub(*lhs))
},
}
}
pub fn saturating_sub(&self, rhs: &Self) -> Self {
match (self, rhs) {
(Positive(lhs), Negative(rhs)) => Positive(lhs.saturating_add(*rhs)),
(Negative(lhs), Positive(rhs)) => Self::safe_new_negative(lhs.saturating_add(*rhs)),
(Positive(lhs), Positive(rhs)) =>
if lhs >= rhs {
Positive(lhs.saturating_sub(*rhs))
} else {
Self::safe_new_negative(rhs.saturating_sub(*lhs))
},
(Negative(lhs), Negative(rhs)) =>
if lhs > rhs {
Self::safe_new_negative(lhs.saturating_sub(*rhs))
} else {
Positive(rhs.saturating_sub(*lhs))
},
}
}
pub fn min(&self, other: &Self) -> Self {
match (self, other) {
(Positive(_), Negative(rhs)) => Self::safe_new_negative(*rhs),
(Negative(lhs), Positive(_)) => Self::safe_new_negative(*lhs),
(Positive(lhs), Positive(rhs)) => Positive((*lhs).min(*rhs)),
(Negative(lhs), Negative(rhs)) => Self::safe_new_negative((*lhs).max(*rhs)),
}
}
}