Skip to content

Commit 7393e0e

Browse files
authored
Merge pull request #116 from ChukwuemekaP1/main
PR: Implement Unified Error Handling Framework closes #74
2 parents 2125f5a + fc44db5 commit 7393e0e

7 files changed

Lines changed: 718 additions & 0 deletions

File tree

contracts/bridge/src/lib.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,91 @@ mod bridge {
1515
#[derive(Debug, PartialEq, Eq, scale::Encode, scale::Decode)]
1616
#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]
1717
pub enum Error {
18+
/// Caller is not authorized
1819
Unauthorized,
20+
/// Token does not exist
1921
TokenNotFound,
22+
/// Invalid chain ID
2023
InvalidChain,
24+
/// Bridge not supported for this token
2125
BridgeNotSupported,
26+
/// Insufficient signatures collected
2227
InsufficientSignatures,
28+
/// Bridge request has expired
2329
RequestExpired,
30+
/// Already signed this request
2431
AlreadySigned,
32+
/// Invalid bridge request
2533
InvalidRequest,
34+
/// Bridge operations are paused
2635
BridgePaused,
36+
/// Invalid metadata
2737
InvalidMetadata,
38+
/// Duplicate bridge request
2839
DuplicateRequest,
40+
/// Gas limit exceeded
2941
GasLimitExceeded,
3042
}
3143

44+
impl core::fmt::Display for Error {
45+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
46+
match self {
47+
Error::Unauthorized => write!(f, "Caller is not authorized"),
48+
Error::TokenNotFound => write!(f, "Token does not exist"),
49+
Error::InvalidChain => write!(f, "Invalid chain ID"),
50+
Error::BridgeNotSupported => write!(f, "Bridge not supported for this token"),
51+
Error::InsufficientSignatures => write!(f, "Insufficient signatures collected"),
52+
Error::RequestExpired => write!(f, "Bridge request has expired"),
53+
Error::AlreadySigned => write!(f, "Already signed this request"),
54+
Error::InvalidRequest => write!(f, "Invalid bridge request"),
55+
Error::BridgePaused => write!(f, "Bridge operations are paused"),
56+
Error::InvalidMetadata => write!(f, "Invalid metadata"),
57+
Error::DuplicateRequest => write!(f, "Duplicate bridge request"),
58+
Error::GasLimitExceeded => write!(f, "Gas limit exceeded"),
59+
}
60+
}
61+
}
62+
63+
impl ContractError for Error {
64+
fn error_code(&self) -> u32 {
65+
match self {
66+
Error::Unauthorized => bridge_codes::BRIDGE_UNAUTHORIZED,
67+
Error::TokenNotFound => bridge_codes::BRIDGE_TOKEN_NOT_FOUND,
68+
Error::InvalidChain => bridge_codes::BRIDGE_INVALID_CHAIN,
69+
Error::BridgeNotSupported => bridge_codes::BRIDGE_NOT_SUPPORTED,
70+
Error::InsufficientSignatures => bridge_codes::BRIDGE_INSUFFICIENT_SIGNATURES,
71+
Error::RequestExpired => bridge_codes::BRIDGE_REQUEST_EXPIRED,
72+
Error::AlreadySigned => bridge_codes::BRIDGE_ALREADY_SIGNED,
73+
Error::InvalidRequest => bridge_codes::BRIDGE_INVALID_REQUEST,
74+
Error::BridgePaused => bridge_codes::BRIDGE_PAUSED,
75+
Error::InvalidMetadata => bridge_codes::BRIDGE_INVALID_METADATA,
76+
Error::DuplicateRequest => bridge_codes::BRIDGE_DUPLICATE_REQUEST,
77+
Error::GasLimitExceeded => bridge_codes::BRIDGE_GAS_LIMIT_EXCEEDED,
78+
}
79+
}
80+
81+
fn error_description(&self) -> &'static str {
82+
match self {
83+
Error::Unauthorized => "Caller does not have permission to perform this operation",
84+
Error::TokenNotFound => "The specified token does not exist",
85+
Error::InvalidChain => "The destination chain ID is invalid",
86+
Error::BridgeNotSupported => "Cross-chain bridging is not supported for this token",
87+
Error::InsufficientSignatures => "Not enough signatures collected for bridge operation",
88+
Error::RequestExpired => "The bridge request has expired and can no longer be executed",
89+
Error::AlreadySigned => "You have already signed this bridge request",
90+
Error::InvalidRequest => "The bridge request is invalid or malformed",
91+
Error::BridgePaused => "Bridge operations are temporarily paused",
92+
Error::InvalidMetadata => "The token metadata is invalid",
93+
Error::DuplicateRequest => "A bridge request with these parameters already exists",
94+
Error::GasLimitExceeded => "The operation exceeded the gas limit",
95+
}
96+
}
97+
98+
fn error_category(&self) -> ErrorCategory {
99+
ErrorCategory::Bridge
100+
}
101+
}
102+
32103
/// Bridge contract for cross-chain property token transfers
33104
#[ink(storage)]
34105
pub struct PropertyBridge {

contracts/compliance_registry/lib.rs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#![cfg_attr(not(feature = "std"), no_std, no_main)]
22

33
use propchain_traits::ComplianceChecker;
4+
use propchain_traits::*;
45

56
#[ink::contract]
67
mod compliance_registry {
@@ -244,19 +245,86 @@ mod compliance_registry {
244245
#[derive(Debug, PartialEq, Eq, scale::Encode, scale::Decode)]
245246
#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]
246247
pub enum Error {
248+
/// Caller is not authorized
247249
NotAuthorized,
250+
/// User is not verified
248251
NotVerified,
252+
/// Verification has expired
249253
VerificationExpired,
254+
/// User has high risk level
250255
HighRisk,
256+
/// Jurisdiction is prohibited
251257
ProhibitedJurisdiction,
258+
/// User already verified
252259
AlreadyVerified,
260+
/// Consent not given
253261
ConsentNotGiven,
262+
/// Data retention period expired
254263
DataRetentionExpired,
264+
/// Invalid risk score
255265
InvalidRiskScore,
266+
/// Invalid document type
256267
InvalidDocumentType,
268+
/// Jurisdiction not supported
257269
JurisdictionNotSupported,
258270
}
259271

272+
impl core::fmt::Display for Error {
273+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
274+
match self {
275+
Error::NotAuthorized => write!(f, "Caller is not authorized"),
276+
Error::NotVerified => write!(f, "User is not verified"),
277+
Error::VerificationExpired => write!(f, "Verification has expired"),
278+
Error::HighRisk => write!(f, "User has high risk level"),
279+
Error::ProhibitedJurisdiction => write!(f, "Jurisdiction is prohibited"),
280+
Error::AlreadyVerified => write!(f, "User already verified"),
281+
Error::ConsentNotGiven => write!(f, "Consent not given"),
282+
Error::DataRetentionExpired => write!(f, "Data retention period expired"),
283+
Error::InvalidRiskScore => write!(f, "Invalid risk score"),
284+
Error::InvalidDocumentType => write!(f, "Invalid document type"),
285+
Error::JurisdictionNotSupported => write!(f, "Jurisdiction not supported"),
286+
}
287+
}
288+
}
289+
290+
impl ContractError for Error {
291+
fn error_code(&self) -> u32 {
292+
match self {
293+
Error::NotAuthorized => propchain_traits::errors::compliance_codes::COMPLIANCE_UNAUTHORIZED,
294+
Error::NotVerified => propchain_traits::errors::compliance_codes::COMPLIANCE_NOT_VERIFIED,
295+
Error::VerificationExpired => propchain_traits::errors::compliance_codes::COMPLIANCE_EXPIRED,
296+
Error::HighRisk => propchain_traits::errors::compliance_codes::COMPLIANCE_CHECK_FAILED,
297+
Error::ProhibitedJurisdiction => propchain_traits::errors::compliance_codes::COMPLIANCE_CHECK_FAILED,
298+
Error::AlreadyVerified => propchain_traits::errors::compliance_codes::COMPLIANCE_UNAUTHORIZED,
299+
Error::ConsentNotGiven => propchain_traits::errors::compliance_codes::COMPLIANCE_NOT_VERIFIED,
300+
Error::DataRetentionExpired => propchain_traits::errors::compliance_codes::COMPLIANCE_EXPIRED,
301+
Error::InvalidRiskScore => propchain_traits::errors::compliance_codes::COMPLIANCE_CHECK_FAILED,
302+
Error::InvalidDocumentType => propchain_traits::errors::compliance_codes::COMPLIANCE_DOCUMENT_MISSING,
303+
Error::JurisdictionNotSupported => propchain_traits::errors::compliance_codes::COMPLIANCE_CHECK_FAILED,
304+
}
305+
}
306+
307+
fn error_description(&self) -> &'static str {
308+
match self {
309+
Error::NotAuthorized => "Caller does not have permission to perform this operation",
310+
Error::NotVerified => "The user has not completed verification",
311+
Error::VerificationExpired => "The user's verification has expired and needs renewal",
312+
Error::HighRisk => "The user has been assessed as high risk",
313+
Error::ProhibitedJurisdiction => "The user's jurisdiction is prohibited",
314+
Error::AlreadyVerified => "The user is already verified",
315+
Error::ConsentNotGiven => "The user has not provided required consent",
316+
Error::DataRetentionExpired => "The data retention period has expired",
317+
Error::InvalidRiskScore => "The risk score is invalid or out of range",
318+
Error::InvalidDocumentType => "The document type is invalid or not supported",
319+
Error::JurisdictionNotSupported => "The jurisdiction is not supported",
320+
}
321+
}
322+
323+
fn error_category(&self) -> ErrorCategory {
324+
ErrorCategory::Compliance
325+
}
326+
}
327+
260328
pub type Result<T> = core::result::Result<T, Error>;
261329

262330
/// Events

contracts/escrow/src/lib.rs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use ink::storage::Mapping;
66
#[cfg(not(feature = "std"))]
77
use scale_info::prelude::{string::String, vec::Vec};
8+
use propchain_traits::*;
89

910
pub mod tests;
1011

@@ -16,21 +17,96 @@ mod propchain_escrow {
1617
#[derive(Debug, PartialEq, Eq, scale::Encode, scale::Decode)]
1718
#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]
1819
pub enum Error {
20+
/// Escrow does not exist
1921
EscrowNotFound,
22+
/// Caller is not authorized
2023
Unauthorized,
24+
/// Invalid escrow status for operation
2125
InvalidStatus,
26+
/// Insufficient funds in escrow
2227
InsufficientFunds,
28+
/// Required conditions not met
2329
ConditionsNotMet,
30+
/// Signature threshold not reached
2431
SignatureThresholdNotMet,
32+
/// Already signed this request
2533
AlreadySigned,
34+
/// Document does not exist
2635
DocumentNotFound,
36+
/// Dispute is currently active
2737
DisputeActive,
38+
/// Time lock period still active
2839
TimeLockActive,
40+
/// Invalid configuration parameters
2941
InvalidConfiguration,
42+
/// Escrow already funded
3043
EscrowAlreadyFunded,
44+
/// Participant not found
3145
ParticipantNotFound,
3246
}
3347

48+
impl core::fmt::Display for Error {
49+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
50+
match self {
51+
Error::EscrowNotFound => write!(f, "Escrow does not exist"),
52+
Error::Unauthorized => write!(f, "Caller is not authorized"),
53+
Error::InvalidStatus => write!(f, "Invalid escrow status for operation"),
54+
Error::InsufficientFunds => write!(f, "Insufficient funds in escrow"),
55+
Error::ConditionsNotMet => write!(f, "Required conditions not met"),
56+
Error::SignatureThresholdNotMet => write!(f, "Signature threshold not reached"),
57+
Error::AlreadySigned => write!(f, "Already signed this request"),
58+
Error::DocumentNotFound => write!(f, "Document does not exist"),
59+
Error::DisputeActive => write!(f, "Dispute is currently active"),
60+
Error::TimeLockActive => write!(f, "Time lock period still active"),
61+
Error::InvalidConfiguration => write!(f, "Invalid configuration parameters"),
62+
Error::EscrowAlreadyFunded => write!(f, "Escrow already funded"),
63+
Error::ParticipantNotFound => write!(f, "Participant not found"),
64+
}
65+
}
66+
}
67+
68+
impl ContractError for Error {
69+
fn error_code(&self) -> u32 {
70+
match self {
71+
Error::EscrowNotFound => propchain_traits::errors::escrow_codes::ESCROW_NOT_FOUND,
72+
Error::Unauthorized => propchain_traits::errors::escrow_codes::UNAUTHORIZED_ACCESS,
73+
Error::InvalidStatus => propchain_traits::errors::escrow_codes::INVALID_STATUS,
74+
Error::InsufficientFunds => propchain_traits::errors::escrow_codes::INSUFFICIENT_ESCROW_FUNDS,
75+
Error::ConditionsNotMet => propchain_traits::errors::escrow_codes::CONDITIONS_NOT_MET,
76+
Error::SignatureThresholdNotMet => propchain_traits::errors::escrow_codes::SIGNATURE_THRESHOLD_NOT_MET,
77+
Error::AlreadySigned => propchain_traits::errors::escrow_codes::ALREADY_SIGNED_ESCROW,
78+
Error::DocumentNotFound => propchain_traits::errors::escrow_codes::DOCUMENT_NOT_FOUND,
79+
Error::DisputeActive => propchain_traits::errors::escrow_codes::DISPUTE_ACTIVE,
80+
Error::TimeLockActive => propchain_traits::errors::escrow_codes::TIME_LOCK_ACTIVE,
81+
Error::InvalidConfiguration => propchain_traits::errors::escrow_codes::INVALID_CONFIGURATION,
82+
Error::EscrowAlreadyFunded => propchain_traits::errors::escrow_codes::ESCROW_ALREADY_FUNDED,
83+
Error::ParticipantNotFound => propchain_traits::errors::escrow_codes::PARTICIPANT_NOT_FOUND,
84+
}
85+
}
86+
87+
fn error_description(&self) -> &'static str {
88+
match self {
89+
Error::EscrowNotFound => "The specified escrow does not exist",
90+
Error::Unauthorized => "Caller does not have permission to perform this operation",
91+
Error::InvalidStatus => "The escrow is not in the required state for this operation",
92+
Error::InsufficientFunds => "The escrow does not have sufficient funds",
93+
Error::ConditionsNotMet => "Not all required conditions have been met",
94+
Error::SignatureThresholdNotMet => "Insufficient signatures collected",
95+
Error::AlreadySigned => "You have already signed this request",
96+
Error::DocumentNotFound => "The requested document does not exist",
97+
Error::DisputeActive => "A dispute is currently active on this escrow",
98+
Error::TimeLockActive => "The time lock period has not yet expired",
99+
Error::InvalidConfiguration => "The escrow configuration is invalid",
100+
Error::EscrowAlreadyFunded => "This escrow has already been funded",
101+
Error::ParticipantNotFound => "The specified participant is not in the escrow",
102+
}
103+
}
104+
105+
fn error_category(&self) -> ErrorCategory {
106+
ErrorCategory::Escrow
107+
}
108+
}
109+
34110
/// Escrow status enumeration
35111
#[derive(Debug, Clone, PartialEq, Eq, scale::Encode, scale::Decode)]
36112
#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]

contracts/fees/src/lib.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use ink::prelude::vec::Vec;
66
use ink::storage::Mapping;
77
use propchain_traits::DynamicFeeProvider;
88
use propchain_traits::FeeOperation;
9+
use propchain_traits::*;
910

1011
/// Dynamic Fee and Market Mechanism contract for PropChain.
1112
/// Implements congestion-based fees, premium listing auctions, validator incentives,
@@ -144,16 +145,71 @@ mod propchain_fees {
144145
#[derive(Debug, PartialEq, Eq, scale::Encode, scale::Decode)]
145146
#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]
146147
pub enum FeeError {
148+
/// Caller is not authorized
147149
Unauthorized,
150+
/// Auction does not exist
148151
AuctionNotFound,
152+
/// Auction has ended
149153
AuctionEnded,
154+
/// Auction has not ended yet
150155
AuctionNotEnded,
156+
/// Bid amount is too low
151157
BidTooLow,
158+
/// Auction already settled
152159
AlreadySettled,
160+
/// Invalid configuration
153161
InvalidConfig,
162+
/// Invalid property ID
154163
InvalidProperty,
155164
}
156165

166+
impl core::fmt::Display for FeeError {
167+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
168+
match self {
169+
FeeError::Unauthorized => write!(f, "Caller is not authorized"),
170+
FeeError::AuctionNotFound => write!(f, "Auction does not exist"),
171+
FeeError::AuctionEnded => write!(f, "Auction has ended"),
172+
FeeError::AuctionNotEnded => write!(f, "Auction has not ended yet"),
173+
FeeError::BidTooLow => write!(f, "Bid amount is too low"),
174+
FeeError::AlreadySettled => write!(f, "Auction already settled"),
175+
FeeError::InvalidConfig => write!(f, "Invalid configuration"),
176+
FeeError::InvalidProperty => write!(f, "Invalid property ID"),
177+
}
178+
}
179+
}
180+
181+
impl ContractError for FeeError {
182+
fn error_code(&self) -> u32 {
183+
match self {
184+
FeeError::Unauthorized => propchain_traits::errors::fee_codes::FEE_UNAUTHORIZED,
185+
FeeError::AuctionNotFound => propchain_traits::errors::fee_codes::FEE_AUCTION_NOT_FOUND,
186+
FeeError::AuctionEnded => propchain_traits::errors::fee_codes::FEE_AUCTION_ENDED,
187+
FeeError::AuctionNotEnded => propchain_traits::errors::fee_codes::FEE_AUCTION_NOT_ENDED,
188+
FeeError::BidTooLow => propchain_traits::errors::fee_codes::FEE_BID_TOO_LOW,
189+
FeeError::AlreadySettled => propchain_traits::errors::fee_codes::FEE_ALREADY_SETTLED,
190+
FeeError::InvalidConfig => propchain_traits::errors::fee_codes::FEE_INVALID_CONFIG,
191+
FeeError::InvalidProperty => propchain_traits::errors::fee_codes::FEE_INVALID_PROPERTY,
192+
}
193+
}
194+
195+
fn error_description(&self) -> &'static str {
196+
match self {
197+
FeeError::Unauthorized => "Caller does not have permission to perform this operation",
198+
FeeError::AuctionNotFound => "The specified auction does not exist",
199+
FeeError::AuctionEnded => "This auction has already ended",
200+
FeeError::AuctionNotEnded => "The auction is still active and has not ended",
201+
FeeError::BidTooLow => "The bid amount is below the minimum required",
202+
FeeError::AlreadySettled => "This auction has already been settled",
203+
FeeError::InvalidConfig => "The fee configuration is invalid",
204+
FeeError::InvalidProperty => "The property ID is invalid or does not exist",
205+
}
206+
}
207+
208+
fn error_category(&self) -> ErrorCategory {
209+
ErrorCategory::Fees
210+
}
211+
}
212+
157213
#[ink(storage)]
158214
pub struct FeeManager {
159215
admin: AccountId,

0 commit comments

Comments
 (0)