Chapter 7.1 // Network Parameters & Deployed Bytecode
[ LIVE TESTNET ]
Polygon Amoy (Chain ID: 80002)
CircularChain Core Protocol Contract:0x3d0bc12948a7192837bc910283748293bc910293
RPC Endpoint:https://rpc-amoy.polygon.technology
Block Time:~2.1 Seconds
Average Gas Fee:< $0.001 (Sponsored)
Chapter 7.2 // Finite State Machine Transitions
[ DETERMINISTIC ESCROW ]
Material Lot On-Chain Lifecycle
STATE 01LISTED
Agent 01 Vision proof & MCX price locked.
STATE 02ESCROW LOCKED
Smelter locks purchase funds in smart contract.
STATE 03TRANSFERRED
Weighbridge mass confirmed; funds released via UPI.
STATE 04EPR MINTED
Avoided carbon NFT minted & retired on CPCB ledger.
Chapter 7.3 // CircularChain.sol InterfaceSOLIDITY v0.8.20
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/metatx/ERC2771Context.sol";
contract CircularChainCore is ERC721, ERC2771Context {
enum LotState { Listed, EscrowLocked, Transferred, EPRMinted, Retired }
struct MaterialLot {
uint256 lotId;
address seller; // Informal Collector
address buyer; // Enterprise Smelter
uint256 massKg;
uint256 purityBps; // e.g. 9850 = 98.50%
uint256 carbonOffsetKg;
string ipfsProofHash; // Pinata CID
LotState state;
}
mapping(uint256 => MaterialLot) public lots;
event LotCreated(uint256 indexed lotId, address indexed seller, uint256 massKg);
event EscrowLocked(uint256 indexed lotId, address indexed buyer);
event OwnershipTransferred(uint256 indexed lotId, address indexed newOwner);
constructor(address trustedForwarder)
ERC721("CircularChain Material Asset", "CCMAT")
ERC2771Context(trustedForwarder) {}
function listMaterial(
uint256 massKg,
uint256 purityBps,
uint256 carbonOffsetKg,
string calldata ipfsProofHash
) external returns (uint256 lotId) {
lotId = uint256(keccak256(abi.encodePacked(_msgSender(), block.timestamp, massKg)));
lots[lotId] = MaterialLot(lotId, _msgSender(), address(0), massKg, purityBps, carbonOffsetKg, ipfsProofHash, LotState.Listed);
_safeMint(_msgSender(), lotId);
emit LotCreated(lotId, _msgSender(), massKg);
}
}