// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import {ERC20Burnable} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol"; contract H11XToken is ERC20, ERC20Burnable, ERC20Permit { uint8 private constant H11X_DECIMALS = 11; uint256 private constant TOKEN_UNIT = 10 ** uint256(H11X_DECIMALS); uint256 public constant VALIDATOR_RESERVE = 2_200_000_000 * TOKEN_UNIT; uint256 public constant PROTOCOL_TREASURY = 2_200_000_000 * TOKEN_UNIT; uint256 public constant ECOSYSTEM = 2_750_000_000 * TOKEN_UNIT; uint256 public constant COMPUTE_REWARDS = 1_650_000_000 * TOKEN_UNIT; uint256 public constant PUBLIC_LIQUIDITY = 1_100_000_000 * TOKEN_UNIT; uint256 public constant FOUNDER_LOCKED = 1_100_000_000 * TOKEN_UNIT; uint256 public constant COMMUNITY_COMPUTE_REWARDS = COMPUTE_REWARDS; uint256 public constant VALIDATOR_SECURITY_REWARDS = VALIDATOR_RESERVE; uint256 public constant ECOSYSTEM_GRANTS = ECOSYSTEM; uint256 public constant FOUNDER_TEAM_VESTED = FOUNDER_LOCKED; uint256 public constant LIQUIDITY_BOOTSTRAP = PUBLIC_LIQUIDITY; uint256 public constant GENESIS_BOOTSTRAP_SUPPLY = 11_000_000_000 * TOKEN_UNIT; error ZeroAllocationAddress(string allocation); error GenesisSupplyMismatch(uint256 minted, uint256 expected); error UnauthorizedIssuanceController(address caller); error InvalidIssuanceController(); error InvalidEvidenceHash(); error DynamicSupplyAmountRequired(); address public issuanceController; event IssuanceControllerUpdated(address indexed previousController, address indexed nextController); event CapabilityBackedH11XIssued( address indexed recipient, uint256 amount, bytes32 indexed evidenceHash, string purpose ); event DynamicH11XRetired( address indexed account, uint256 amount, bytes32 indexed evidenceHash, string purpose ); constructor( address communityComputeRewards, address validatorSecurityRewards, address ecosystemGrants, address protocolTreasury, address founderTeamVested, address liquidityBootstrap ) ERC20("H11X", "H11X") ERC20Permit("H11X") { _mintGenesis(communityComputeRewards, COMPUTE_REWARDS, "communityComputeRewards"); _mintGenesis(validatorSecurityRewards, VALIDATOR_RESERVE, "validatorSecurityRewards"); _mintGenesis(ecosystemGrants, ECOSYSTEM, "ecosystemGrants"); _mintGenesis(protocolTreasury, PROTOCOL_TREASURY, "protocolTreasury"); _mintGenesis(founderTeamVested, FOUNDER_LOCKED, "founderTeamVested"); _mintGenesis(liquidityBootstrap, PUBLIC_LIQUIDITY, "liquidityBootstrap"); if (totalSupply() != GENESIS_BOOTSTRAP_SUPPLY) { revert GenesisSupplyMismatch(totalSupply(), GENESIS_BOOTSTRAP_SUPPLY); } issuanceController = protocolTreasury; emit IssuanceControllerUpdated(address(0), protocolTreasury); } function decimals() public pure override returns (uint8) { return H11X_DECIMALS; } function setIssuanceController(address nextController) external { if (msg.sender != issuanceController) { revert UnauthorizedIssuanceController(msg.sender); } if (nextController == address(0)) { revert InvalidIssuanceController(); } address previousController = issuanceController; issuanceController = nextController; emit IssuanceControllerUpdated(previousController, nextController); } function issueCapabilityBackedH11X( address recipient, uint256 amount, bytes32 evidenceHash, string calldata purpose ) external { if (msg.sender != issuanceController) { revert UnauthorizedIssuanceController(msg.sender); } if (recipient == address(0)) { revert ZeroAllocationAddress("dynamicIssuanceRecipient"); } if (amount == 0) { revert DynamicSupplyAmountRequired(); } if (evidenceHash == bytes32(0)) { revert InvalidEvidenceHash(); } _mint(recipient, amount); emit CapabilityBackedH11XIssued(recipient, amount, evidenceHash, purpose); } function retireDynamicH11X( uint256 amount, bytes32 evidenceHash, string calldata purpose ) external { if (amount == 0) { revert DynamicSupplyAmountRequired(); } if (evidenceHash == bytes32(0)) { revert InvalidEvidenceHash(); } _burn(msg.sender, amount); emit DynamicH11XRetired(msg.sender, amount, evidenceHash, purpose); } function _mintGenesis(address recipient, uint256 amount, string memory allocation) private { if (recipient == address(0)) { revert ZeroAllocationAddress(allocation); } _mint(recipient, amount); } }