// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import "./ReserveAttestationOracle.sol"; /** * @title InstitutionalSettlementDollar (AET-USD v2) * @notice Production-Grade Regulated Institutional Settlement & Clearing Currency * @dev Enforces hard on-chain reserve gating, stale-data rejection, risk buffers, * OFAC/FinCEN compliance freezing, and timelocked oracle upgrades. */ contract InstitutionalSettlementDollar { string public name = "Aeterna Institutional Settlement Dollar"; string public symbol = "AET-USD"; uint8 public constant decimals = 6; uint256 public totalSupply; // --- Balances & Allowances --- mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; // --- Governance & Compliance Roles --- address public owner; address public pendingOwner; address public masterMinter; address public complianceOfficer; // FinCEN / OFAC Sanctions Administrator address public pauser; // --- Proof of Reserve Gatekeeper --- IReserveAttestationOracle public reserveOracle; address public pendingOracle; uint256 public oracleUpgradeTimelock; uint256 public constant TIMELOCK_DELAY = 48 hours; // --- Quotas & Sanctions Storage --- mapping(address => bool) public minters; mapping(address => uint256) public minterAllowance; mapping(address => bool) public isFrozen; bool public paused; // --- EIP-2612 Gasless Permit Storage --- bytes32 public DOMAIN_SEPARATOR; mapping(address => uint256) public nonces; bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9; // --- Events --- event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); event Mint(address indexed minter, address indexed to, uint256 amount, uint256 reserveBufferRemaining); event Burn(address indexed burner, uint256 amount); event AddressFrozen(address indexed target, string reason); event AddressUnfrozen(address indexed target); event DirtyFundsConfiscated(address indexed target, uint256 amountWiped); event OracleUpgradeInitiated(address indexed pendingOracle, uint256 unlockTimestamp); event OracleUpgradeExecuted(address indexed activeOracle); event OwnershipTransferInitiated(address indexed previousOwner, address indexed newOwner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); event MinterConfigured(address indexed minter, uint256 quota); event MinterRemoved(address indexed minter); event MasterMinterUpdated(address indexed previousMinter, address indexed newMinter); event ComplianceOfficerUpdated(address indexed previousOfficer, address indexed newOfficer); event PauserUpdated(address indexed previousPauser, address indexed newPauser); modifier onlyOwner() { require(msg.sender == owner, "Ownable: caller not owner"); _; } modifier onlyMasterMinter() { require(msg.sender == masterMinter || msg.sender == owner, "Minter: unauthorized"); _; } modifier onlyCompliance() { require(msg.sender == complianceOfficer || msg.sender == owner, "Compliance: unauthorized"); _; } modifier whenNotPaused() { require(!paused, "Pausable: paused"); _; } modifier notFrozen(address account) { require(!isFrozen[account], "Compliance: address is frozen"); _; } constructor( address _owner, address _masterMinter, address _complianceOfficer, address _pauser, address _reserveOracle ) { require(_owner != address(0) && _reserveOracle != address(0), "Zero address"); owner = _owner; masterMinter = _masterMinter; complianceOfficer = _complianceOfficer; pauser = _pauser; reserveOracle = IReserveAttestationOracle(_reserveOracle); DOMAIN_SEPARATOR = keccak256( abi.encode( keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), keccak256(bytes(name)), keccak256(bytes("1")), block.chainid, address(this) ) ); } function balanceOf(address account) external view returns (uint256) { return _balances[account]; } function allowance(address _owner, address _spender) external view returns (uint256) { return _allowances[_owner][_spender]; } // --- Hard-Gated Institutional Minting --- function mint(address to, uint256 amount) external whenNotPaused notFrozen(to) returns (bool) { require(minters[msg.sender] || msg.sender == masterMinter || msg.sender == owner, "Unauthorized minter"); // 1. Quota Check if (msg.sender != owner) { require(minterAllowance[msg.sender] >= amount, "Minter allowance exceeded"); minterAllowance[msg.sender] -= amount; } // 2. HARD ON-CHAIN RESERVE & STALENESS GATE (bool eligible, uint256 maxPermittedSupply) = reserveOracle.verifyMintFeasibility(totalSupply, amount); require(eligible, "MINT REJECTED: Oracle reports reserve deficit, stale data (>24h), or risk buffer breach"); require(totalSupply + amount <= maxPermittedSupply, "MINT REJECTED: Exceeds net verified eligible reserves"); totalSupply += amount; _balances[to] += amount; uint256 bufferRemaining = maxPermittedSupply - totalSupply; emit Mint(msg.sender, to, amount, bufferRemaining); emit Transfer(address(0), to, amount); return true; } function burn(uint256 amount) external whenNotPaused notFrozen(msg.sender) returns (bool) { require(_balances[msg.sender] >= amount, "Insufficient burn balance"); _balances[msg.sender] -= amount; totalSupply -= amount; emit Burn(msg.sender, amount); emit Transfer(msg.sender, address(0), amount); return true; } function transfer(address to, uint256 amount) external whenNotPaused notFrozen(msg.sender) notFrozen(to) returns (bool) { _transfer(msg.sender, to, amount); return true; } function transferFrom(address from, address to, uint256 amount) external whenNotPaused notFrozen(msg.sender) notFrozen(from) notFrozen(to) returns (bool) { uint256 currentAllowance = _allowances[from][msg.sender]; require(currentAllowance >= amount, "Transfer exceeds allowance"); unchecked { _approve(from, msg.sender, currentAllowance - amount); } _transfer(from, to, amount); return true; } function approve(address spender, uint256 amount) external whenNotPaused notFrozen(msg.sender) notFrozen(spender) returns (bool) { _approve(msg.sender, spender, amount); return true; } function _transfer(address from, address to, uint256 amount) internal { require(from != address(0) && to != address(0), "Zero address transfer"); require(_balances[from] >= amount, "Insufficient funds"); unchecked { _balances[from] -= amount; _balances[to] += amount; } emit Transfer(from, to, amount); } function _approve(address _owner, address _spender, uint256 amount) internal { require(_owner != address(0) && _spender != address(0), "Zero address approve"); _allowances[_owner][_spender] = amount; emit Approval(_owner, _spender, amount); } // --- Law Enforcement, OFAC Sanctions & Confiscation --- function freeze(address target, string calldata reason) external onlyCompliance { isFrozen[target] = true; emit AddressFrozen(target, reason); } function unfreeze(address target) external onlyCompliance { isFrozen[target] = false; emit AddressUnfrozen(target); } function wipeAccount(address target) external onlyCompliance { require(isFrozen[target], "Account must be frozen before wiping"); uint256 dirtyBalance = _balances[target]; require(dirtyBalance > 0, "No balance to wipe"); _balances[target] = 0; totalSupply -= dirtyBalance; emit DirtyFundsConfiscated(target, dirtyBalance); emit Transfer(target, address(0), dirtyBalance); } // --- Timelocked Oracle Upgrade Governance --- function initiateOracleUpgrade(address _newOracle) external onlyOwner { require(_newOracle != address(0), "Zero address"); pendingOracle = _newOracle; oracleUpgradeTimelock = block.timestamp + TIMELOCK_DELAY; emit OracleUpgradeInitiated(_newOracle, oracleUpgradeTimelock); } function executeOracleUpgrade() external onlyOwner { require(pendingOracle != address(0), "No pending oracle"); require(block.timestamp >= oracleUpgradeTimelock, "Timelock not expired (48h delay required)"); reserveOracle = IReserveAttestationOracle(pendingOracle); emit OracleUpgradeExecuted(pendingOracle); pendingOracle = address(0); } // --- Two-Step Ownership Handover --- function transferOwnership(address newOwner) external onlyOwner { require(newOwner != address(0), "New owner cannot be zero address"); require(newOwner != owner, "Cannot transfer to current owner"); pendingOwner = newOwner; emit OwnershipTransferInitiated(owner, newOwner); } function acceptOwnership() external { require(msg.sender == pendingOwner, "Caller is not pending owner"); address previousOwner = owner; owner = pendingOwner; pendingOwner = address(0); emit OwnershipTransferred(previousOwner, owner); } // --- Minter Administration --- function configureMinter(address minter, uint256 quota) external onlyMasterMinter { require(minter != address(0), "Zero minter address"); minters[minter] = true; minterAllowance[minter] = quota; emit MinterConfigured(minter, quota); } function removeMinter(address minter) external onlyMasterMinter { require(minters[minter], "Not an active minter"); minters[minter] = false; minterAllowance[minter] = 0; emit MinterRemoved(minter); } // --- Key Governance Role Setters --- function setMasterMinter(address _masterMinter) external onlyOwner { require(_masterMinter != address(0), "Zero address"); emit MasterMinterUpdated(masterMinter, _masterMinter); masterMinter = _masterMinter; } function setComplianceOfficer(address _compliance) external onlyOwner { require(_compliance != address(0), "Zero address"); emit ComplianceOfficerUpdated(complianceOfficer, _compliance); complianceOfficer = _compliance; } function setPauser(address _pauser) external onlyOwner { require(_pauser != address(0), "Zero address"); emit PauserUpdated(pauser, _pauser); pauser = _pauser; } function setPaused(bool _paused) external { require(msg.sender == pauser || msg.sender == owner, "Unauthorized"); paused = _paused; } }