use crate::blueprints::access_controller::AccessControllerError;
use crate::blueprints::account::AccountError;
use crate::blueprints::consensus_manager::{ConsensusManagerError, ValidatorError};
use crate::blueprints::package::PackageError;
use crate::blueprints::pool::v1::errors::{
multi_resource_pool::Error as MultiResourcePoolError,
one_resource_pool::Error as OneResourcePoolError,
two_resource_pool::Error as TwoResourcePoolError,
};
use crate::blueprints::resource::{AuthZoneError, NonFungibleVaultError};
use crate::blueprints::resource::{
BucketError, FungibleResourceManagerError, NonFungibleResourceManagerError, ProofError,
VaultError, WorktopError,
};
use crate::blueprints::transaction_processor::TransactionProcessorError;
use crate::internal_prelude::*;
use crate::kernel::call_frame::{
CallFrameDrainSubstatesError, CallFrameRemoveSubstateError, CallFrameScanKeysError,
CallFrameScanSortedSubstatesError, CallFrameSetSubstateError, CloseSubstateError,
CreateFrameError, CreateNodeError, DropNodeError, MarkTransientSubstateError,
MovePartitionError, OpenSubstateError, PassMessageError, PinNodeError, ReadSubstateError,
WriteSubstateError,
};
use crate::object_modules::metadata::MetadataError;
use crate::object_modules::role_assignment::RoleAssignmentError;
use crate::object_modules::royalty::ComponentRoyaltyError;
use crate::system::system_modules::auth::AuthError;
use crate::system::system_modules::costing::CostingError;
use crate::system::system_modules::limits::TransactionLimitsError;
use crate::system::system_type_checker::TypeCheckError;
use crate::transaction::AbortReason;
use crate::vm::wasm::WasmRuntimeError;
use crate::vm::ScryptoVmVersionError;
use radix_engine_interface::api::object_api::ModuleId;
use radix_engine_interface::api::{ActorStateHandle, AttachedModuleId};
use radix_engine_interface::blueprints::package::{BlueprintPartitionType, CanonicalBlueprintId};
use radix_transactions::model::IntentHash;
use sbor::representations::PrintMode;
#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor)]
pub enum IdAllocationError {
OutOfID,
}
pub trait CanBeAbortion {
fn abortion(&self) -> Option<&AbortReason>;
}
pub mod error_models {
use radix_common::prelude::*;
#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, ScryptoSbor)]
#[sbor(
as_type = "Reference",
as_ref = "&Reference(self.0)",
from_value = "Self(value.0)",
type_name = "NodeId"
)]
pub struct ReferencedNodeId(pub radix_common::prelude::NodeId);
impl Debug for ReferencedNodeId {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
self.0.fmt(f)
}
}
impl From<radix_common::prelude::NodeId> for ReferencedNodeId {
fn from(value: radix_common::prelude::NodeId) -> Self {
Self(value)
}
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, ScryptoSbor)]
#[sbor(
as_type = "Own",
as_ref = "&Own(self.0)",
from_value = "Self(value.0)",
type_name = "NodeId"
)]
pub struct OwnedNodeId(pub radix_common::prelude::NodeId);
impl Debug for OwnedNodeId {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
self.0.fmt(f)
}
}
impl From<radix_common::prelude::NodeId> for OwnedNodeId {
fn from(value: radix_common::prelude::NodeId) -> Self {
Self(value)
}
}
}
lazy_static::lazy_static! {
static ref HISTORIC_REJECTION_REASON_SCHEMAS: [ScryptoSingleTypeSchema; 1] = {
[
ScryptoSingleTypeSchema::from(include_bytes!("rejection_reason_cuttlefish_schema.bin")),
]
};
}
#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor)]
pub enum RejectionReason {
TransactionEpochNotYetValid {
valid_from: Epoch,
current_epoch: Epoch,
},
TransactionEpochNoLongerValid {
valid_until: Epoch,
current_epoch: Epoch,
},
TransactionProposerTimestampNotYetValid {
valid_from_inclusive: Instant,
current_time: Instant,
},
TransactionProposerTimestampNoLongerValid {
valid_to_exclusive: Instant,
current_time: Instant,
},
IntentHashPreviouslyCommitted(IntentHash),
IntentHashPreviouslyCancelled(IntentHash),
BootloadingError(BootloadingError),
ErrorBeforeLoanAndDeferredCostsRepaid(RuntimeError),
SuccessButFeeLoanNotRepaid,
SubintentsNotYetSupported,
}
impl<'a> ContextualDisplay<ScryptoValueDisplayContext<'a>> for RejectionReason {
type Error = fmt::Error;
fn contextual_format(
&self,
f: &mut fmt::Formatter,
context: &ScryptoValueDisplayContext,
) -> Result<(), Self::Error> {
self.create_persistable().contextual_format(f, context)
}
}
impl RejectionReason {
pub fn create_persistable(&self) -> PersistableRejectionReason {
PersistableRejectionReason {
schema_index: HISTORIC_REJECTION_REASON_SCHEMAS.len() as u32 - 1,
encoded_rejection_reason: scrypto_decode(&scrypto_encode(self).unwrap()).unwrap(),
}
}
}
#[derive(Debug, Clone, ScryptoSbor)]
pub struct PersistableRejectionReason {
pub schema_index: u32,
pub encoded_rejection_reason: ScryptoOwnedRawValue,
}
impl<'a> ContextualDisplay<ScryptoValueDisplayContext<'a>> for PersistableRejectionReason {
type Error = fmt::Error;
fn contextual_format(
&self,
f: &mut fmt::Formatter,
context: &ScryptoValueDisplayContext,
) -> Result<(), Self::Error> {
let value = &self.encoded_rejection_reason;
let formatted_optional = HISTORIC_REJECTION_REASON_SCHEMAS
.get(self.schema_index as usize)
.and_then(|schema| {
format_debug_like_value(
f,
schema,
value,
sbor::representations::PrintMode::SingleLine,
*context,
)
});
match formatted_optional {
Some(result) => result,
None => match scrypto_encode(&value) {
Ok(encoded) => write!(f, "UnknownRejectionReason({})", hex::encode(encoded)),
Err(error) => write!(f, "CannotDisplayRejectionReason({error:?})"),
},
}
}
}
fn format_debug_like_value(
f: &mut impl fmt::Write,
schema: &SingleTypeSchema<ScryptoCustomSchema>,
value: &ScryptoRawValue,
print_mode: PrintMode,
custom_context: ScryptoValueDisplayContext,
) -> Option<fmt::Result> {
use sbor::representations::*;
let type_id = schema.type_id;
let schema = schema.schema.as_unique_version();
let depth_limit = SCRYPTO_SBOR_V1_MAX_DEPTH;
validate_partial_payload_against_schema::<ScryptoCustomExtension, _>(
value.value_body_bytes(),
traversal::ExpectedStart::ValueBody(value.value_kind()),
true,
0,
schema,
type_id,
&(),
depth_limit,
)
.ok()?;
let display_parameters = ValueDisplayParameters::Annotated {
display_mode: DisplayMode::RustLike(RustLikeOptions::debug_like()),
print_mode,
custom_context,
schema,
type_id,
depth_limit,
};
Some(write!(f, "{}", value.display(display_parameters)))
}
impl From<BootloadingError> for RejectionReason {
fn from(value: BootloadingError) -> Self {
RejectionReason::BootloadingError(value)
}
}
#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor)]
pub enum TransactionExecutionError {
BootloadingError(BootloadingError),
RuntimeError(RuntimeError),
}
#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor)]
pub enum BootloadingError {
ReferencedNodeDoesNotExist(error_models::ReferencedNodeId),
ReferencedNodeIsNotAnObject(error_models::ReferencedNodeId),
ReferencedNodeDoesNotAllowDirectAccess(error_models::ReferencedNodeId),
FailedToApplyDeferredCosts(CostingError),
}
lazy_static::lazy_static! {
static ref HISTORIC_RUNTIME_ERROR_SCHEMAS: [ScryptoSingleTypeSchema; 2] = {
[
ScryptoSingleTypeSchema::from(include_bytes!("runtime_error_pre_cuttlefish_schema.bin")),
ScryptoSingleTypeSchema::from(include_bytes!("runtime_error_cuttlefish_schema.bin")),
]
};
}
#[derive(Clone, PartialEq, Eq, ScryptoSbor, Debug)]
pub enum RuntimeError {
KernelError(KernelError),
SystemError(SystemError),
SystemModuleError(SystemModuleError),
SystemUpstreamError(SystemUpstreamError),
VmError(VmError),
ApplicationError(ApplicationError),
FinalizationCostingError(CostingError),
}
impl<'a> ContextualDisplay<ScryptoValueDisplayContext<'a>> for RuntimeError {
type Error = fmt::Error;
fn contextual_format(
&self,
f: &mut fmt::Formatter,
context: &ScryptoValueDisplayContext,
) -> Result<(), Self::Error> {
self.create_persistable().contextual_format(f, context)
}
}
impl RuntimeError {
pub fn create_persistable(&self) -> PersistableRuntimeError {
PersistableRuntimeError {
schema_index: HISTORIC_RUNTIME_ERROR_SCHEMAS.len() as u32 - 1,
encoded_error: scrypto_decode(&scrypto_encode(self).unwrap()).unwrap(),
}
}
}
#[derive(Debug, Clone, ScryptoSbor)]
pub struct PersistableRuntimeError {
pub schema_index: u32,
pub encoded_error: ScryptoOwnedRawValue,
}
impl<'a> ContextualDisplay<ScryptoValueDisplayContext<'a>> for PersistableRuntimeError {
type Error = fmt::Error;
fn contextual_format(
&self,
f: &mut fmt::Formatter,
context: &ScryptoValueDisplayContext,
) -> Result<(), Self::Error> {
let value = &self.encoded_error;
let formatted_optional = HISTORIC_RUNTIME_ERROR_SCHEMAS
.get(self.schema_index as usize)
.and_then(|schema| {
format_debug_like_value(f, schema, value, PrintMode::SingleLine, *context)
});
match formatted_optional {
Some(result) => result,
None => match scrypto_encode(&value) {
Ok(encoded) => write!(f, "UnknownError({})", hex::encode(encoded)),
Err(error) => write!(f, "CannotDisplayError({error:?})"),
},
}
}
}
impl SystemApiError for RuntimeError {}
impl From<KernelError> for RuntimeError {
fn from(error: KernelError) -> Self {
RuntimeError::KernelError(error)
}
}
impl From<SystemUpstreamError> for RuntimeError {
fn from(error: SystemUpstreamError) -> Self {
RuntimeError::SystemUpstreamError(error)
}
}
impl From<SystemModuleError> for RuntimeError {
fn from(error: SystemModuleError) -> Self {
RuntimeError::SystemModuleError(error)
}
}
impl From<ApplicationError> for RuntimeError {
fn from(error: ApplicationError) -> Self {
RuntimeError::ApplicationError(error)
}
}
impl CanBeAbortion for RuntimeError {
fn abortion(&self) -> Option<&AbortReason> {
match self {
RuntimeError::KernelError(_) => None,
RuntimeError::VmError(_) => None,
RuntimeError::SystemError(_) => None,
RuntimeError::SystemUpstreamError(_) => None,
RuntimeError::SystemModuleError(err) => err.abortion(),
RuntimeError::ApplicationError(_) => None,
RuntimeError::FinalizationCostingError(_) => None,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor)]
pub enum KernelError {
CallFrameError(CallFrameError),
IdAllocationError(IdAllocationError),
SubstateHandleDoesNotExist(SubstateHandle),
OrphanedNodes(Vec<error_models::OwnedNodeId>),
StackError(StackError),
}
#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor)]
pub struct InvalidDropAccess {
pub node_id: error_models::ReferencedNodeId,
pub package_address: PackageAddress,
pub blueprint_name: String,
pub actor_package: Option<PackageAddress>,
}
#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor)]
pub struct InvalidGlobalizeAccess {
pub package_address: PackageAddress,
pub blueprint_name: String,
pub actor_package: Option<PackageAddress>,
}
impl CanBeAbortion for VmError {
fn abortion(&self) -> Option<&AbortReason> {
match self {
VmError::Wasm(err) => err.abortion(),
_ => None,
}
}
}
impl From<CallFrameError> for KernelError {
fn from(value: CallFrameError) -> Self {
KernelError::CallFrameError(value)
}
}
#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor)]
pub enum CallFrameError {
CreateFrameError(CreateFrameError),
PassMessageError(PassMessageError),
CreateNodeError(CreateNodeError),
DropNodeError(DropNodeError),
PinNodeError(PinNodeError),
MovePartitionError(MovePartitionError),
MarkTransientSubstateError(MarkTransientSubstateError),
OpenSubstateError(OpenSubstateError),
CloseSubstateError(CloseSubstateError),
ReadSubstateError(ReadSubstateError),
WriteSubstateError(WriteSubstateError),
ScanSubstatesError(CallFrameScanKeysError),
DrainSubstatesError(CallFrameDrainSubstatesError),
ScanSortedSubstatesError(CallFrameScanSortedSubstatesError),
SetSubstatesError(CallFrameSetSubstateError),
RemoveSubstatesError(CallFrameRemoveSubstateError),
}
#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor)]
pub enum StackError {
InvalidStackId,
}
#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor)]
pub enum SystemError {
NoBlueprintId,
NoPackageAddress,
InvalidActorStateHandle,
InvalidActorRefHandle,
GlobalizingTransientBlueprint,
GlobalAddressDoesNotExist,
NotAnAddressReservation,
NotAnObject,
NotAKeyValueStore,
ModulesDontHaveOuterObjects,
ActorNodeIdDoesNotExist,
OuterObjectDoesNotExist,
NotAFieldHandle,
NotAFieldWriteHandle,
RootHasNoType,
AddressBech32EncodeError,
TypeCheckError(TypeCheckError),
FieldDoesNotExist(BlueprintId, u8),
CollectionIndexDoesNotExist(BlueprintId, u8),
CollectionIndexIsOfWrongType(
BlueprintId,
u8,
BlueprintPartitionType,
BlueprintPartitionType,
),
KeyValueEntryLocked,
FieldLocked(ActorStateHandle, u8),
ObjectModuleDoesNotExist(AttachedModuleId),
NotAKeyValueEntryHandle,
NotAKeyValueEntryWriteHandle,
InvalidLockFlags,
CannotGlobalize(CannotGlobalizeError),
MissingModule(ModuleId),
InvalidGlobalAddressReservation,
InvalidChildObjectCreation,
InvalidModuleType(Box<InvalidModuleType>),
CreateObjectError(Box<CreateObjectError>),
InvalidGenericArgs,
InvalidFeature(String),
AssertAccessRuleFailed,
BlueprintDoesNotExist(CanonicalBlueprintId),
AuthTemplateDoesNotExist(CanonicalBlueprintId),
InvalidGlobalizeAccess(Box<InvalidGlobalizeAccess>),
InvalidDropAccess(Box<InvalidDropAccess>),
CostingModuleNotEnabled,
AuthModuleNotEnabled,
TransactionRuntimeModuleNotEnabled,
ForceWriteEventFlagsNotAllowed,
BlueprintTypeNotFound(String),
BlsError(String),
InputDataEmpty,
SystemPanic(String),
CannotLockFeeInChildSubintent(usize),
IntentError(IntentError),
}
#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor)]
pub enum IntentError {
CannotVerifyParentOnRoot,
CannotYieldProof,
VerifyParentFailed,
InvalidIntentIndex(usize),
NoParentToYieldTo,
AssertNextCallReturnsFailed(ResourceConstraintsError),
AssertBucketContentsFailed(ResourceConstraintError),
}
#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor)]
pub enum EventError {
SchemaNotFoundError {
blueprint: BlueprintId,
event_name: String,
},
EventSchemaNotMatch(String),
NoAssociatedPackage,
InvalidActor,
}
#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor)]
pub enum SystemUpstreamError {
SystemFunctionCallNotAllowed,
FnNotFound(String),
ReceiverNotMatch(String),
HookNotFound(BlueprintHook),
InputDecodeError(DecodeError),
InputSchemaNotMatch(String, String),
OutputDecodeError(DecodeError),
OutputSchemaNotMatch(String, String),
}
#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor)]
pub enum VmError {
Native(NativeRuntimeError),
Wasm(WasmRuntimeError),
ScryptoVmVersion(ScryptoVmVersionError),
}
#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor)]
pub enum NativeRuntimeError {
InvalidCodeId,
Trap {
export_name: String,
input: ScryptoValue,
error: String,
},
}
#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor)]
pub enum CreateObjectError {
BlueprintNotFound(String),
InvalidFieldDueToFeature(BlueprintId, u8),
MissingField(BlueprintId, u8),
InvalidFieldIndex(BlueprintId, u8),
SchemaValidationError(BlueprintId, String),
InvalidSubstateWrite(String),
}
#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor)]
pub enum SystemModuleError {
AuthError(AuthError),
CostingError(CostingError),
TransactionLimitsError(TransactionLimitsError),
EventError(Box<EventError>),
}
#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor)]
pub struct InvalidModuleType {
pub expected_blueprint: BlueprintId,
pub actual_blueprint: BlueprintId,
}
#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor)]
pub enum CannotGlobalizeError {
NotAnObject,
AlreadyGlobalized,
InvalidBlueprintId,
}
impl CanBeAbortion for SystemModuleError {
fn abortion(&self) -> Option<&AbortReason> {
match self {
Self::CostingError(err) => err.abortion(),
_ => None,
}
}
}
impl From<AuthError> for SystemModuleError {
fn from(error: AuthError) -> Self {
Self::AuthError(error)
}
}
impl From<CostingError> for SystemModuleError {
fn from(error: CostingError) -> Self {
Self::CostingError(error)
}
}
#[derive(Debug, Clone)]
pub enum InvokeError<E: SelfError> {
SelfError(E),
Downstream(RuntimeError),
}
pub trait SelfError {
fn into_runtime_error(self) -> RuntimeError;
}
impl<E: Into<ApplicationError>> SelfError for E {
fn into_runtime_error(self) -> RuntimeError {
self.into().into()
}
}
impl<E: SelfError> From<RuntimeError> for InvokeError<E> {
fn from(runtime_error: RuntimeError) -> Self {
InvokeError::Downstream(runtime_error)
}
}
impl<E: SelfError> From<E> for InvokeError<E> {
fn from(error: E) -> Self {
InvokeError::SelfError(error)
}
}
impl<E: SelfError> InvokeError<E> {
pub fn error(error: E) -> Self {
InvokeError::SelfError(error)
}
pub fn downstream(runtime_error: RuntimeError) -> Self {
InvokeError::Downstream(runtime_error)
}
}
impl<E: SelfError> From<InvokeError<E>> for RuntimeError {
fn from(error: InvokeError<E>) -> Self {
match error {
InvokeError::Downstream(runtime_error) => runtime_error,
InvokeError::SelfError(e) => e.into_runtime_error(),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor)]
pub enum ApplicationError {
ExportDoesNotExist(String),
InputDecodeError(DecodeError),
PanicMessage(String),
RoleAssignmentError(RoleAssignmentError),
MetadataError(MetadataError),
ComponentRoyaltyError(ComponentRoyaltyError),
TransactionProcessorError(TransactionProcessorError),
PackageError(PackageError),
ConsensusManagerError(ConsensusManagerError),
ValidatorError(ValidatorError),
FungibleResourceManagerError(FungibleResourceManagerError),
NonFungibleResourceManagerError(NonFungibleResourceManagerError),
BucketError(BucketError),
ProofError(ProofError),
NonFungibleVaultError(NonFungibleVaultError),
VaultError(VaultError),
WorktopError(WorktopError),
AuthZoneError(AuthZoneError),
AccountError(AccountError),
AccessControllerError(AccessControllerError),
OneResourcePoolError(OneResourcePoolError),
TwoResourcePoolError(TwoResourcePoolError),
MultiResourcePoolError(MultiResourcePoolError),
}
impl From<TransactionProcessorError> for ApplicationError {
fn from(value: TransactionProcessorError) -> Self {
Self::TransactionProcessorError(value)
}
}
impl From<PackageError> for ApplicationError {
fn from(value: PackageError) -> Self {
Self::PackageError(value)
}
}
impl From<ConsensusManagerError> for ApplicationError {
fn from(value: ConsensusManagerError) -> Self {
Self::ConsensusManagerError(value)
}
}
impl From<FungibleResourceManagerError> for ApplicationError {
fn from(value: FungibleResourceManagerError) -> Self {
Self::FungibleResourceManagerError(value)
}
}
impl From<RoleAssignmentError> for ApplicationError {
fn from(value: RoleAssignmentError) -> Self {
Self::RoleAssignmentError(value)
}
}
impl From<BucketError> for ApplicationError {
fn from(value: BucketError) -> Self {
Self::BucketError(value)
}
}
impl From<ProofError> for ApplicationError {
fn from(value: ProofError) -> Self {
Self::ProofError(value)
}
}
impl From<VaultError> for ApplicationError {
fn from(value: VaultError) -> Self {
Self::VaultError(value)
}
}
impl From<WorktopError> for ApplicationError {
fn from(value: WorktopError) -> Self {
Self::WorktopError(value)
}
}
impl From<AuthZoneError> for ApplicationError {
fn from(value: AuthZoneError) -> Self {
Self::AuthZoneError(value)
}
}
impl From<OpenSubstateError> for CallFrameError {
fn from(value: OpenSubstateError) -> Self {
Self::OpenSubstateError(value)
}
}
impl From<CloseSubstateError> for CallFrameError {
fn from(value: CloseSubstateError) -> Self {
Self::CloseSubstateError(value)
}
}
impl From<PassMessageError> for CallFrameError {
fn from(value: PassMessageError) -> Self {
Self::PassMessageError(value)
}
}
impl From<MovePartitionError> for CallFrameError {
fn from(value: MovePartitionError) -> Self {
Self::MovePartitionError(value)
}
}
impl From<ReadSubstateError> for CallFrameError {
fn from(value: ReadSubstateError) -> Self {
Self::ReadSubstateError(value)
}
}
impl From<WriteSubstateError> for CallFrameError {
fn from(value: WriteSubstateError) -> Self {
Self::WriteSubstateError(value)
}
}
impl From<CreateNodeError> for CallFrameError {
fn from(value: CreateNodeError) -> Self {
Self::CreateNodeError(value)
}
}
impl From<DropNodeError> for CallFrameError {
fn from(value: DropNodeError) -> Self {
Self::DropNodeError(value)
}
}
impl From<CreateFrameError> for CallFrameError {
fn from(value: CreateFrameError) -> Self {
Self::CreateFrameError(value)
}
}
impl From<CallFrameScanKeysError> for CallFrameError {
fn from(value: CallFrameScanKeysError) -> Self {
Self::ScanSubstatesError(value)
}
}
impl From<CallFrameScanSortedSubstatesError> for CallFrameError {
fn from(value: CallFrameScanSortedSubstatesError) -> Self {
Self::ScanSortedSubstatesError(value)
}
}
impl From<CallFrameDrainSubstatesError> for CallFrameError {
fn from(value: CallFrameDrainSubstatesError) -> Self {
Self::DrainSubstatesError(value)
}
}
impl From<CallFrameSetSubstateError> for CallFrameError {
fn from(value: CallFrameSetSubstateError) -> Self {
Self::SetSubstatesError(value)
}
}
impl From<CallFrameRemoveSubstateError> for CallFrameError {
fn from(value: CallFrameRemoveSubstateError) -> Self {
Self::RemoveSubstatesError(value)
}
}
impl<T> From<T> for RuntimeError
where
T: Into<CallFrameError>,
{
fn from(value: T) -> Self {
Self::KernelError(KernelError::CallFrameError(value.into()))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn the_current_runtime_error_schema_is_last_on_historic_list() {
let latest = HISTORIC_RUNTIME_ERROR_SCHEMAS.last().unwrap();
let current = generate_single_type_schema::<RuntimeError, ScryptoCustomSchema>();
compare_single_type_schemas(
&SchemaComparisonSettings::require_equality(),
latest,
¤t,
)
.assert_valid("latest", "current");
}
#[test]
fn the_current_runtime_error_schema_has_no_raw_node_ids() {
let current = generate_single_type_schema::<RuntimeError, ScryptoCustomSchema>();
assert_no_raw_node_ids(¤t);
}
#[test]
fn the_current_rejection_reason_schema_is_last_on_historic_list() {
let latest = HISTORIC_REJECTION_REASON_SCHEMAS.last().unwrap();
let current = generate_single_type_schema::<RejectionReason, ScryptoCustomSchema>();
compare_single_type_schemas(
&SchemaComparisonSettings::require_equality(),
latest,
¤t,
)
.assert_valid("latest", "current");
}
#[test]
fn the_current_rejection_reason_schema_has_no_raw_node_ids() {
let current = generate_single_type_schema::<RejectionReason, ScryptoCustomSchema>();
assert_no_raw_node_ids(¤t);
}
fn assert_no_raw_node_ids(schema: &SingleTypeSchema<ScryptoCustomSchema>) {
let schema = schema.schema.as_unique_version();
for (type_kind, type_metadata) in schema.type_kinds.iter().zip(schema.type_metadata.iter())
{
if type_metadata.type_name.as_deref() == Some("NodeId") {
match type_kind {
TypeKind::Custom(ScryptoCustomTypeKind::Own)
| TypeKind::Custom(ScryptoCustomTypeKind::Reference) => {}
_ => {
let mut formatted_schema = String::new();
format_debug_like_value(
&mut formatted_schema,
&generate_single_type_schema::<
SchemaV1<ScryptoCustomSchema>,
ScryptoCustomSchema,
>(),
&scrypto_decode(&scrypto_encode(schema).unwrap()).unwrap(),
PrintMode::MultiLine {
indent_size: 4,
base_indent: 4,
first_line_indent: 4,
},
ScryptoValueDisplayContext::default(),
);
panic!("A raw NodeId was detected somewhere in the error schema. Use `error_models::ReferencedNodeId` or `error_models::OwnedNodeId` instead.\n\nSchema:\n{}", formatted_schema);
}
}
}
}
}
#[test]
fn runtime_error_string() {
let network = NetworkDefinition::mainnet();
let address_encoder = AddressBech32Encoder::new(&network);
let address_encoder = Some(&address_encoder);
{
let runtime_error = RuntimeError::ApplicationError(ApplicationError::AccountError(
AccountError::VaultDoesNotExist {
resource_address: XRD,
},
));
let debugged = format!("{:?}", runtime_error);
assert_eq!(debugged, "ApplicationError(AccountError(VaultDoesNotExist { resource_address: ResourceAddress(5da66318c6318c61f5a61b4c6318c6318cf794aa8d295f14e6318c6318c6) }))");
let rendered = runtime_error.to_string(address_encoder);
assert_eq!(rendered, "ApplicationError(AccountError(VaultDoesNotExist { resource_address: ResourceAddress(\"resource_rdx1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxradxrd\") }))");
}
{
let mut id_allocator = crate::kernel::id_allocator::IdAllocator::new(hash("seed-data"));
let bucket_entity_type = EntityType::InternalGenericComponent;
let example_bucket_1 = id_allocator.allocate_node_id(bucket_entity_type).unwrap();
let example_bucket_2 = id_allocator.allocate_node_id(bucket_entity_type).unwrap();
let runtime_error = RuntimeError::KernelError(KernelError::OrphanedNodes(vec![
example_bucket_1.into(),
example_bucket_2.into(),
]));
let debugged = format!("{:?}", runtime_error);
assert_eq!(debugged, "KernelError(OrphanedNodes([NodeId(\"f82ee60dbc11caa1594fccdbb8031c41af8084344bcbe7a4c784491a7d4c\"), NodeId(\"f8abce267317b7bdd859951840ccd25f1ea7e83c538d507e0f82da7b9aed\")]))");
let rendered = runtime_error.to_string(address_encoder);
assert_eq!(rendered, "KernelError(OrphanedNodes([NodeId(\"internal_component_rdx1lqhwvrduz892zk20endmsqcugxhcppp5f0970fx8s3y35l2vv5mzfn\"), NodeId(\"internal_component_rdx1lz4uufnnz7mmmkzej5vypnxjtu0206pu2wx4qls0std8hxhd3v84yv\")]))");
}
}
}