#
Redemption
At maturity, token holders redeem their tokens for principal repayment. Tokens are burned and the bond lifecycle completes.
#
Redemption Flow
sequenceDiagram
participant ISSUER as Issuer
participant ML as Master Ledger
participant HOLDER as Holder
participant CF as Chain Fusion
participant BANK as Settlement
Note over ISSUER,BANK: Approaching Maturity
ISSUER->>ML: Initiate Redemption
ML->>ML: Set status = Maturing
ML->>ML: Disable new mints
ML->>HOLDER: Notify Redemption
HOLDER->>ML: Submit Redemption Request
ML->>ML: Lock Tokens
ISSUER->>BANK: Fund Settlement
BANK-->>HOLDER: Principal Paid
HOLDER->>ML: Confirm Receipt
ML->>CF: Burn Cross-chain Tokens
CF->>CF: Execute Burns
ML->>ML: Burn ICP Tokens
ML->>ML: Set status = Redeemed
#
Redemption Types
#
Scheduled Maturity
Normal redemption at bond maturity date:
flowchart LR
MATURE[Maturity Date] --> NOTICE[30-Day Notice]
NOTICE --> REQUESTS[Collect Requests]
REQUESTS --> SETTLE[Settlement]
SETTLE --> BURN[Token Burn]
#
Early Redemption
Issuer calls bonds before maturity (if permitted):
flowchart LR
CALL[Issuer Call] --> NOTICE[Notice Period]
NOTICE --> PREMIUM[Calculate Premium]
PREMIUM --> SETTLE[Settlement]
SETTLE --> BURN[Token Burn]
#
Partial Redemption
Redeem portion of holdings (if permitted):
type PartialRedemption = record {
holder : Principal;
token_id : TokenId;
amount : nat; // Tokens to redeem
remaining : nat; // Tokens to keep
};
#
Maturity Process
#
Timeline
gantt
title Redemption Timeline
dateFormat YYYY-MM-DD
section Notice
Maturity Announcement :2027-01-22, 7d
Trading Restriction :2027-01-29, 21d
section Collection
Request Window :2027-02-12, 10d
Request Deadline :milestone, 2027-02-22, 0d
section Settlement
Funding :2027-02-22, 3d
Payment Processing :2027-02-25, 5d
Token Burn :2027-03-02, 1d
#
Phase 1: Announcement
type RedemptionAnnouncement = record {
token_id : TokenId;
maturity_date : Timestamp;
redemption_price : nat; // Per token
currency : Text;
request_deadline : Timestamp;
payment_date : Timestamp;
instructions : Text;
};
30 days before maturity:
- Announce redemption to all holders
- Publish redemption price
- Open request submission window
#
Phase 2: Request Collection
Holders submit redemption requests:
type RedemptionRequest = record {
id : RequestId;
holder : Principal;
token_id : TokenId;
amount : nat;
payment_method : PaymentMethod;
bank_details : opt BankDetails;
wallet_address : opt Text; // For stablecoin payment
submitted_at : Timestamp;
status : RequestStatus;
};
type PaymentMethod = variant {
BankWire : BankDetails;
Stablecoin : StablecoinDetails;
};
type BankDetails = record {
account_holder : Text;
iban : Text;
swift : Text;
bank_name : Text;
bank_address : Text;
reference : opt Text;
};
type StablecoinDetails = record {
chain : Chain;
address : Text;
currency : Text; // "USDC", "USDT"
};
#
Phase 3: Token Locking
Upon request submission, tokens are locked:
stateDiagram-v2
[*] --> Active: Tokens tradeable
Active --> Locked: Redemption requested
Locked --> Burned: Payment confirmed
Locked --> Active: Request cancelled
note right of Locked: Cannot transfer
#
Phase 4: Settlement
sequenceDiagram
participant ISSUER as Issuer
participant ESCROW as Escrow
participant HOLDER as Holder
ISSUER->>ESCROW: Deposit Funds
Note over ESCROW: Verify sufficient funds
loop For Each Request
ESCROW->>HOLDER: Process Payment
alt Bank Wire
ESCROW->>HOLDER: Wire Transfer
else Stablecoin
ESCROW->>HOLDER: On-chain Transfer
end
end
#
Phase 5: Token Burn
After payment confirmation:
flowchart TB
CONFIRM[Payment Confirmed] --> COLLECT[Collect Tokens]
COLLECT --> ICP_BURN[Burn ICP Tokens]
COLLECT --> EVM_BURN[Burn EVM Tokens]
COLLECT --> SOL_BURN[Burn Solana Tokens]
ICP_BURN & EVM_BURN & SOL_BURN --> VERIFY[Verify Total Burned]
VERIFY --> COMPLETE[Mark Redeemed]
#
Redemption Pricing
#
At Par
Most common - tokens redeemed at face value:
Redemption Value = Token Balance × Denomination
Example: 100 tokens × $1,000 = $100,000
#
With Premium (Early Redemption)
Issuer pays premium for calling early:
Redemption Value = Token Balance × Denomination × (1 + Premium)
Example: 100 tokens × $1,000 × 1.02 = $102,000 (2% premium)
#
Below Par
Rare - only in distressed situations:
Redemption Value = Token Balance × Denomination × Recovery Rate
Example: 100 tokens × $1,000 × 0.80 = $80,000 (80% recovery)
#
Cross-Chain Burns
#
Burn Process
sequenceDiagram
participant ML as Master Ledger
participant CF as Chain Fusion
participant EVM as EVM Chain
participant SOL as Solana
ML->>CF: Initiate Burns
par Burn on EVM
CF->>EVM: Call burn()
EVM-->>CF: TX Hash
and Burn on Solana
CF->>SOL: Burn instruction
SOL-->>CF: Signature
end
CF->>CF: Wait for confirmations
CF->>ML: Report Burns Complete
ML->>ML: Update total_supply
#
Burn Verification
All burns must be verified before closing:
type BurnVerification = record {
chain : Chain;
expected_amount : nat;
actual_burned : nat;
tx_hash : Text;
block_number : nat64;
verified : bool;
};
#
Canister Interface
candid
service : {
// Issuer operations
initiate_redemption : (TokenId) -> (Result<RedemptionId, Error>);
set_redemption_price : (RedemptionId, nat) -> (Result<(), Error>);
fund_redemption : (RedemptionId) -> (Result<(), Error>);
process_payments : (RedemptionId) -> (Result<ProcessingResult, Error>);
finalize_redemption : (RedemptionId) -> (Result<(), Error>);
// Holder operations
submit_redemption_request : (SubmitRequestArgs) -> (Result<RequestId, Error>);
update_payment_details : (RequestId, PaymentMethod) -> (Result<(), Error>);
cancel_request : (RequestId) -> (Result<(), Error>);
confirm_payment : (RequestId) -> (Result<(), Error>);
// Queries
get_redemption : (RedemptionId) -> (opt Redemption) query;
get_my_requests : () -> (vec RedemptionRequest) query;
get_redemption_status : (TokenId) -> (RedemptionStatus) query;
}
type SubmitRequestArgs = record {
token_id : TokenId;
amount : nat;
payment_method : PaymentMethod;
};
type ProcessingResult = record {
total_requests : nat32;
processed : nat32;
failed : nat32;
total_amount : nat;
};
#
Redemption States
stateDiagram-v2
[*] --> Active: Token Active
Active --> Announced: Maturity Approaching
Announced --> Collecting: Request Window Open
Collecting --> Processing: Deadline Passed
Processing --> Settling: Payments in Progress
Settling --> Burning: All Paid
Burning --> Redeemed: Tokens Burned
Redeemed --> [*]
Processing --> Disputed: Payment Issues
Disputed --> Settling: Resolved
#
Token Status Transitions
#
Edge Cases
#
Unreachable Holders
flowchart TB
HOLDER[Holder Unreachable] --> ATTEMPT[Multiple Contact Attempts]
ATTEMPT --> ESCROW[Funds in Escrow]
ESCROW --> WAIT[Wait Period: 1 Year]
WAIT --> CLAIM{Claimed?}
CLAIM -->|Yes| PAY[Pay Holder]
CLAIM -->|No| ESCHEAT[Escheat Process]
#
Lost Wallet Access
type WalletRecovery = record {
holder : Principal;
old_address : Text;
new_address : Text;
kyc_verification : Text; // Re-verify identity
approved_by : Principal;
approved_at : Timestamp;
};
#
Disputed Payments
flowchart TB
DISPUTE[Payment Dispute] --> REVIEW[Review Evidence]
REVIEW --> DECISION{Valid Dispute?}
DECISION -->|Yes| RETRY[Retry Payment]
DECISION -->|No| CLOSE[Close Dispute]
RETRY --> VERIFY[Verify Receipt]
VERIFY --> PROCEED[Continue Redemption]
#
Events
type RedemptionEvent = variant {
Announced : record {
token_id : TokenId;
maturity_date : Timestamp;
redemption_price : nat;
timestamp : Timestamp;
};
RequestSubmitted : record {
request_id : RequestId;
holder : Principal;
amount : nat;
timestamp : Timestamp;
};
PaymentProcessed : record {
request_id : RequestId;
amount : nat;
method : Text;
timestamp : Timestamp;
};
TokensBurned : record {
token_id : TokenId;
chain : Chain;
amount : nat;
tx_hash : Text;
timestamp : Timestamp;
};
Completed : record {
token_id : TokenId;
total_redeemed : nat;
total_burned : nat;
timestamp : Timestamp;
};
};