18 on chain flow
Overview
This document provides a complete end-to-end walkthrough of on-chain operations, from project approval to credit retirement, with concrete examples and transaction flows.
Complete On-Chain Flow Diagram
Project Approved (PoAI + Governance)
↓
Mint ProjectRecord (NFT)
↓
Configure Credit Units Contract
↓
Issue Credit Units (Semi-Fungible Mint)
↓
User Holds Credits
↓
Retirement (Burn)
↓
Certificate Generation (Off-Chain)Step 1: Project Approved (PoAI + Governance)
Prerequisites
PoAI verification completed (off-chain)
PoAI proof hashes generated:
poaiBundleHashpoaiAssetHashpoaiDataHashpoaiProcessHash
Governance vote passed
Issuance cap approved: 10,000 tons
On-Chain Action
Transaction: mintProjectRecord
projectRegistry.mintProjectRecord(
projectId = 101,
metadataHash = 0xabc123...,
capUnits = 10_000 * UNIT, // 10,000,000,000 (if UNIT = 1e6)
poaiBundleHash = 0xdef456...,
poaiAssetHash = 0x789ghi...,
poaiDataHash = 0x123jkl...,
poaiProcessHash = 0x456mno...
);Result:
ProjectRecord NFT minted with
tokenId = 101PoAI hashes stored on-chain
Cap stored: 10,000,000,000 units
Status: Active
Event Emitted:
event ProjectRecordMinted(
uint256 indexed projectId = 101,
uint256 indexed tokenId = 101,
uint256 maxIssuableUnits = 10_000_000_000,
bytes32 poaiBundleHash = 0xdef456...
);Step 2: Configure Credit Units Contract
On-Chain Action
Transaction: setProjectConfig
carbonCredit1155.setProjectConfig(
tokenId = 101, // Same as ProjectRecord tokenId
capUnits = 10_000 * UNIT, // 10,000,000,000
policy = TransferPolicy.OPEN,
active = true
);Validations:
✅ ProjectRecord exists (tokenId 101)
✅ PoAI approved (hashes non-zero)
✅ Cap > 0
Result:
Project tokenId 101 configured
Cap set: 10,000,000,000 units
Transfer policy: OPEN
Status: Active (can mint credits)
Event Emitted:
event ProjectConfigured(
uint256 indexed tokenId = 101,
uint256 capUnits = 10_000_000_000,
TransferPolicy policy = OPEN,
bool active = true
);Step 3: Issue Credit Units (Semi-Fungible Mint)
Scenario: Issue 2,000 Credits to Treasury
On-Chain Action:
Transaction: mintCredits
carbonCredit1155.mintCredits(
tokenId = 101,
to = treasuryAddress, // 0xTreasury...
amountUnits = 2_000 * UNIT // 2,000,000,000 units
);Validations:
✅ Project active (tokenId 101)
✅
issued[101] + 2_000_000_000 <= cap[101]0 + 2_000_000_000 <= 10_000_000_000✅
State Changes:
issued[101] = 2_000_000_000balanceOf(treasuryAddress, 101) = 2_000_000_000Total supply for tokenId 101: 2,000,000,000 units
Event Emitted:
event CreditsMinted(
uint256 indexed tokenId = 101,
address indexed to = treasuryAddress,
uint256 amountUnits = 2_000_000_000
);Step 4: User Holds Credits
Scenario A: Retail User Buys 0.25 Tons
Purchase Flow (Pattern A: On-Chain Swap):
Transaction: transfer (from marketplace contract)
// Marketplace contract transfers from treasury to user
carbonCredit1155.safeTransferFrom(
from = treasuryAddress,
to = userAddress, // 0xUser...
id = 101,
amount = 0.25 * UNIT // 250,000 units
);State Changes:
balanceOf(treasuryAddress, 101) = 1_999_750_000balanceOf(userAddress, 101) = 250_000
UI Display:
const balanceUnits = await contract.balanceOf(userAddress, 101);
const balanceTons = balanceUnits / UNIT; // 0.25
// Display: "You own 0.25 tons from Solar Rajasthan 2024"Scenario B: Enterprise Buys 12,437.62 Tons
Purchase Flow:
carbonCredit1155.safeTransferFrom(
from = treasuryAddress,
to = enterpriseAddress, // 0xEnterprise...
id = 101,
amount = 12_437.62 * UNIT // 12,437,620,000 units
);State Changes:
balanceOf(treasuryAddress, 101) = 1_987_312_380balanceOf(enterpriseAddress, 101) = 12_437_620_000
UI Display:
const balanceUnits = await contract.balanceOf(enterpriseAddress, 101);
const balanceTons = balanceUnits / UNIT; // 12.43762
// Display: "You own 12,437.62 tons from Solar Rajasthan 2024"Step 5: Retirement (Burn)
Scenario: Retail User Retires 0.25 Tons
On-Chain Action:
Transaction: retire
carbonCredit1155.retire(
tokenId = 101,
amountUnits = 0.25 * UNIT // 250,000 units
);Validations:
✅
balanceOf(msg.sender, 101) >= 250_000User has 250,000 units ✅
State Changes:
balanceOf(userAddress, 101) = 0(burned)retired[101] = 250_000Total supply for tokenId 101: 1,999,750,000 units (reduced by 250,000)
Event Emitted:
event CreditsRetired(
uint256 indexed tokenId = 101,
address indexed from = userAddress,
uint256 amountUnits = 250_000
);Transaction Hash: 0xRetirementTxHash...
Step 6: Certificate Generation (Off-Chain)
Indexer Listens to Event
Event Received:
{
"event": "CreditsRetired",
"tokenId": 101,
"from": "0xUser...",
"amountUnits": 250000,
"transactionHash": "0xRetirementTxHash...",
"blockNumber": 12345678,
"timestamp": 1705238400
}Certificate Generation
Backend Service:
Fetch Project Details:
ProjectRecord tokenId 101
Project name: "Solar Rajasthan 2024"
PoAI proof hashes
Generate Certificate:
{
"certificateId": "CERT-123",
"project": {
"id": "PJT-101",
"name": "Solar Rajasthan 2024",
"tokenId": 101
},
"retirement": {
"quantity": 0.25,
"quantityUnits": 250000,
"retiredBy": "0xUser...",
"timestamp": "2026-01-14T10:00:00Z",
"transactionHash": "0xRetirementTxHash..."
},
"poai": {
"bundleHash": "0xdef456...",
"assetHash": "0x789ghi...",
"dataHash": "0x123jkl...",
"processHash": "0x456mno..."
},
"onChainProof": {
"contractAddress": "0xCarbonCredit1155...",
"tokenId": 101,
"eventIndex": 0
}
}Generate PDF Certificate:
Human-readable format
Includes all certificate data
Platform branding
Store Certificate:
PDF stored (S3/IPFS)
JSON metadata stored
Certificate URI generated
Notify User:
Email notification
In-app notification
Certificate download link
Complete Example: Solar Project Rajasthan
Initial State
Project: Solar Rajasthan 2024
Cap: 10,000 tons
UNIT: 1e6
Cap Units: 10,000,000,000
Step-by-Step Transactions
1. Mint ProjectRecord
2. Configure Credits
3. Issue Credits
4. Retail Purchase
5. Retirement
6. Certificate Generated
Indexer detects
CreditsRetiredeventCertificate service generates certificate
Certificate includes:
Project: Solar Rajasthan 2024
Quantity: 0.25 tons
Transaction: 0xRetirementTxHash...
PoAI: 0xdef456...
State Tracking
Project State
Balance State
Available Supply
Event Flow Summary
Last updated