// SPDX-License-Identifier: MIT pragma solidity ^0.8.19; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "@openzeppelin/contracts/utils/Pausable.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "../compliance/LegallyCompliantBase.sol"; /** * @title CompliantUSDC * @notice USD Coin (Compliant) - ERC20 token with full legal compliance * @dev Inherits from LegallyCompliantBase for Travel Rules exemption and regulatory compliance exemption */ contract CompliantUSDC is ERC20, Pausable, Ownable, LegallyCompliantBase { uint8 private constant DECIMALS = 6; /** * @notice Constructor * @param initialOwner Address that will own the contract * @param admin Address that will receive DEFAULT_ADMIN_ROLE for compliance */ constructor( address initialOwner, address admin ) ERC20("USD Coin (Compliant)", "cUSDC") Ownable(initialOwner) LegallyCompliantBase(admin) { // Mint initial supply to deployer _mint(msg.sender, 1000000 * 10**DECIMALS); } /** * @notice Returns the number of decimals * @return Number of decimals (6 for USDC) */ function decimals() public pure override returns (uint8) { return DECIMALS; } /** * @notice Internal transfer override with compliance tracking * @param from Source address * @param to Destination address * @param amount Transfer amount */ function _update( address from, address to, uint256 amount ) internal override whenNotPaused { // Perform the transfer super._update(from, to, amount); // Emit compliant value transfer event if (from != address(0) && to != address(0)) { bytes32 legalRefHash = _generateLegalReferenceHash( from, to, amount, abi.encodePacked("cUSDC Transfer") ); emit ValueTransferDeclared(from, to, amount, legalRefHash); } } /** * @notice Pause token transfers * @dev Only owner can pause */ function pause() public onlyOwner { _pause(); } /** * @notice Unpause token transfers * @dev Only owner can unpause */ function unpause() public onlyOwner { _unpause(); } /** * @notice Mint new tokens * @param to Address to mint tokens to * @param amount Amount of tokens to mint * @dev Only owner can mint */ function mint(address to, uint256 amount) public onlyOwner { _mint(to, amount); } /** * @notice Burn tokens from caller's balance * @param amount Amount of tokens to burn */ function burn(uint256 amount) public { _burn(msg.sender, amount); } }