#
Minting
Token minting creates the on-chain ERC-3643 representation of a bond on the ICP Master Ledger, following TradFi settlement and delivery of the bond into custody. Supply is fixed and capped to the subscribed amount, linked to the specific ISIN compartment.
#
Minting Flow
sequenceDiagram
participant ISSUER as Issuer
participant II as Issuer Interface
participant ML as Master Ledger
participant STORE as Metadata Store
participant CF as Chain Fusion
participant EVM as EVM (Plume / Base / Canton)
ISSUER->>II: Create Token Request
II->>II: Validate Issuer Auth
II->>ML: create_token(params)
ML->>ML: Validate Parameters
ML->>ML: Generate Token ID
ML->>STORE: Store Metadata
ML->>ML: Mint Initial Supply
ML->>ML: Assign to Issuer Treasury
ML-->>II: Token Created
II-->>ISSUER: Token ID + Details
Note over CF,EVM: ERC-3643 contracts deployed on live chains
ISSUER->>CF: Deploy ERC-3643 contracts
CF->>EVM: Deploy token + Identity Registry + Compliance Module
EVM-->>CF: Contract addresses
#
Token Creation
#
Create Token Request
type CreateTokenArgs = record {
// Bond identification
isin : Text;
name : Text;
symbol : Text;
// Token parameters
total_supply : nat;
decimals : nat8;
// Bond metadata
bond_metadata : BondMetadata;
// ERC-3643 compliance configuration
compliance_config : ComplianceConfig;
};
type BondMetadata = record {
issuer_name : Text;
issuer_id : Text;
maturity_date : Timestamp;
coupon_rate_bps : nat16; // Basis points (e.g., 750 = 7.5%)
coupon_frequency : CouponFrequency;
collateral_type : Text;
collateral_location : Text;
spv_compartment : Text; // Luxembourg SPV compartment ID
prospectus_hash : Text;
legal_docs_hash : Text;
};
type ComplianceConfig = record {
kyc_required : bool;
geographic_restrictions : vec Text; // e.g., ["US"]
min_investment : nat; // EUR/USD 100,000
accreditation_required : bool;
lock_period : opt Duration;
max_holders : opt nat32;
};
#
Token ID Generation
Token IDs are deterministically generated from the ISIN:
Token ID = SHA256(ISIN || Canister ID || Timestamp)
= "trtg_ch1234567890_a1b2c3..."
#
Token Data Model
#
On-Chain Token Record
type Token = record {
// Identity
id : TokenId;
isin : Text;
name : Text;
symbol : Text;
// Supply
total_supply : nat;
circulating_supply : nat;
decimals : nat8;
// Metadata
bond_metadata : BondMetadata;
// State
status : TokenStatus;
created_at : Timestamp;
created_by : Principal;
// ERC-3643 compliance
compliance_config : ComplianceConfig;
// Treasury
treasury_balance : nat;
// Live chain deployments
chain_deployments : vec ChainDeployment;
};
type ChainDeployment = record {
chain : Chain;
token_contract : Text; // ERC-3643 token address
identity_registry : Text; // Identity Registry address
compliance_module : Text; // Compliance Module address
};
type TokenStatus = variant {
Pending; // Created but not yet active
Active; // Transfers enabled on live chains
Suspended; // Transfers halted
Matured; // Past maturity date
Redeemed; // Fully redeemed, tokens burned
};
#
Initial State
After minting, the token is in this state:
#
ERC-3643 Contract Deployment
When a token is minted, ERC-3643 contracts are deployed on each live chain:
flowchart TB
MINT[Token Minted on ICP] --> DEPLOY[Deploy ERC-3643 Contracts]
DEPLOY --> PLUME_D[Plume Deployment]
DEPLOY --> BASE_D[Base Deployment]
DEPLOY --> CANTON_D[Canton Deployment]
subgraph "Per-Chain Deployment"
TOKEN[ERC-3643 Token Contract]
IR[Identity Registry]
CM[Compliance Module]
end
PLUME_D --> TOKEN
BASE_D --> TOKEN
CANTON_D --> TOKENEach deployment includes:
- Token Contract: ERC-3643 permissioned token with fixed supply
- Identity Registry: Wallet-to-identity bindings, synchronized from ICP KYC Registry via Chain Fusion
- Compliance Module: Per-token rules (investor caps, geographic restrictions, lockups)
#
Validation Rules
#
Pre-Mint Validation
flowchart TB
REQ[Create Token Request] --> V1{Valid ISIN?}
V1 -->|No| E1[Error: Invalid ISIN]
V1 -->|Yes| V2{ISIN Unique?}
V2 -->|No| E2[Error: ISIN Exists]
V2 -->|Yes| V3{Valid Symbol?}
V3 -->|No| E3[Error: Invalid Symbol]
V3 -->|Yes| V4{Valid Supply?}
V4 -->|No| E4[Error: Invalid Supply]
V4 -->|Yes| V5{Valid Metadata?}
V5 -->|No| E5[Error: Invalid Metadata]
V5 -->|Yes| MINT[Proceed with Minting]
#
Validation Checks
#
Issuer Treasury
After minting, all tokens are held in the issuer's treasury until distribution:
flowchart LR
MINT[Mint Tokens] --> TREASURY[Issuer Treasury]
TREASURY --> DIST1[Distribution to Investor A]
TREASURY --> DIST2[Distribution to Investor B]
TREASURY --> DIST3[Distribution to Investor C]
#
Token Activation
After minting and ERC-3643 contract deployment, the token must be activated before transfers are enabled:
sequenceDiagram
participant ISSUER as Issuer
participant ML as Master Ledger
Note over ISSUER,ML: Token in Pending state
ISSUER->>ML: activate_token(token_id)
ML->>ML: Verify all metadata present
ML->>ML: Verify ERC-3643 contracts deployed on all live chains
ML->>ML: Verify Identity Registry synchronized
ML->>ML: Set status = Active
ML-->>ISSUER: Token Activated
Note over ISSUER,ML: Transfers now enabled
#
Activation Checklist
Before activation:
- All metadata fields populated
- Document hashes verified
- Luxembourg SPV compartment confirmed
- ERC-3643 contracts deployed on Plume, Base, Canton
- Identity Registry synchronized with ICP KYC Registry
- Compliance Module configured with correct rules
- Issuer treasury funded