use crate::{H160, U256};
use alloc::{string::String, vec::Vec};
use codec::{Decode, Encode, MaxEncodedLen};
use frame_support::weights::Weight;
use pallet_revive_uapi::ReturnFlags;
use scale_info::TypeInfo;
use sp_runtime::{
traits::{Saturating, Zero},
DispatchError, RuntimeDebug,
};
#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)]
pub enum DepositLimit<Balance> {
UnsafeOnlyForDryRun,
Balance(Balance),
}
impl<T> DepositLimit<T> {
pub fn is_unchecked(&self) -> bool {
match self {
Self::UnsafeOnlyForDryRun => true,
_ => false,
}
}
}
impl<T> From<T> for DepositLimit<T> {
fn from(value: T) -> Self {
Self::Balance(value)
}
}
#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)]
pub struct ContractResult<R, Balance> {
pub gas_consumed: Weight,
pub gas_required: Weight,
pub storage_deposit: StorageDeposit<Balance>,
pub result: Result<R, DispatchError>,
}
#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)]
pub struct EthTransactInfo<Balance> {
pub gas_required: Weight,
pub storage_deposit: Balance,
pub eth_gas: U256,
pub data: Vec<u8>,
}
#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)]
pub enum EthTransactError {
Data(Vec<u8>),
Message(String),
}
pub enum ConversionPrecision {
Exact,
RoundUp,
}
pub type CodeUploadResult<Balance> = Result<CodeUploadReturnValue<Balance>, DispatchError>;
pub type GetStorageResult = Result<Option<Vec<u8>>, ContractAccessError>;
#[derive(Copy, Clone, Eq, PartialEq, Encode, Decode, MaxEncodedLen, RuntimeDebug, TypeInfo)]
pub enum ContractAccessError {
DoesntExist,
KeyDecodingFailed,
}
#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo, Default)]
pub struct ExecReturnValue {
pub flags: ReturnFlags,
pub data: Vec<u8>,
}
impl ExecReturnValue {
pub fn did_revert(&self) -> bool {
self.flags.contains(ReturnFlags::REVERT)
}
}
#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)]
pub struct InstantiateReturnValue {
pub result: ExecReturnValue,
pub addr: H160,
}
#[derive(Clone, PartialEq, Eq, Encode, Decode, MaxEncodedLen, RuntimeDebug, TypeInfo)]
pub struct CodeUploadReturnValue<Balance> {
pub code_hash: sp_core::H256,
pub deposit: Balance,
}
#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)]
pub enum Code {
Upload(Vec<u8>),
Existing(sp_core::H256),
}
#[derive(
Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, MaxEncodedLen, RuntimeDebug, TypeInfo,
)]
pub enum StorageDeposit<Balance> {
Refund(Balance),
Charge(Balance),
}
impl<Balance: Zero> Default for StorageDeposit<Balance> {
fn default() -> Self {
Self::Charge(Zero::zero())
}
}
impl<Balance: Zero + Copy> StorageDeposit<Balance> {
pub fn charge_or_zero(&self) -> Balance {
match self {
Self::Charge(amount) => *amount,
Self::Refund(_) => Zero::zero(),
}
}
pub fn is_zero(&self) -> bool {
match self {
Self::Charge(amount) => amount.is_zero(),
Self::Refund(amount) => amount.is_zero(),
}
}
}
impl<Balance> StorageDeposit<Balance>
where
Balance: Saturating + Ord + Copy,
{
pub fn saturating_add(&self, rhs: &Self) -> Self {
use StorageDeposit::*;
match (self, rhs) {
(Charge(lhs), Charge(rhs)) => Charge(lhs.saturating_add(*rhs)),
(Refund(lhs), Refund(rhs)) => Refund(lhs.saturating_add(*rhs)),
(Charge(lhs), Refund(rhs)) =>
if lhs >= rhs {
Charge(lhs.saturating_sub(*rhs))
} else {
Refund(rhs.saturating_sub(*lhs))
},
(Refund(lhs), Charge(rhs)) =>
if lhs > rhs {
Refund(lhs.saturating_sub(*rhs))
} else {
Charge(rhs.saturating_sub(*lhs))
},
}
}
pub fn saturating_sub(&self, rhs: &Self) -> Self {
use StorageDeposit::*;
match (self, rhs) {
(Charge(lhs), Refund(rhs)) => Charge(lhs.saturating_add(*rhs)),
(Refund(lhs), Charge(rhs)) => Refund(lhs.saturating_add(*rhs)),
(Charge(lhs), Charge(rhs)) =>
if lhs >= rhs {
Charge(lhs.saturating_sub(*rhs))
} else {
Refund(rhs.saturating_sub(*lhs))
},
(Refund(lhs), Refund(rhs)) =>
if lhs > rhs {
Refund(lhs.saturating_sub(*rhs))
} else {
Charge(rhs.saturating_sub(*lhs))
},
}
}
pub fn available(&self, limit: &Balance) -> Balance {
use StorageDeposit::*;
match self {
Charge(amount) => limit.saturating_sub(*amount),
Refund(amount) => limit.saturating_add(*amount),
}
}
}