// SPDX-License-Identifier: MIT pragma solidity ^0.8.19; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "@openzeppelin/contracts/access/AccessControl.sol"; /** * @title CompliantWrappedToken * @notice ERC-20 wrapper for bridged compliant tokens (cWUSDT, cWUSDC, etc.) on public chains. * @dev Only MINTER_ROLE can mint (e.g. CCIP receiver/bridge); BURNER_ROLE can burn (bridge-back). * Admin can grant/revoke roles. Used for cW* representation of Chain 138 compliant tokens. */ contract CompliantWrappedToken is ERC20, AccessControl { bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE"); uint8 private immutable _decimalsStorage; constructor( string memory name_, string memory symbol_, uint8 decimals_, address admin_ ) ERC20(name_, symbol_) { _decimalsStorage = decimals_; _grantRole(DEFAULT_ADMIN_ROLE, admin_); _grantRole(MINTER_ROLE, admin_); _grantRole(BURNER_ROLE, admin_); } function decimals() public view override returns (uint8) { return _decimalsStorage; } /// @notice Mint to account (only MINTER_ROLE, e.g. bridge receiver). function mint(address to, uint256 amount) external onlyRole(MINTER_ROLE) { _mint(to, amount); } /// @notice Burn from account (only BURNER_ROLE, e.g. bridge for burn-on-exit). function burn(address from, uint256 amount) external onlyRole(BURNER_ROLE) { _burn(from, amount); } /// @notice Burn from account (only BURNER_ROLE). Enables TwoWayTokenBridgeL2 and other bridges that call burnFrom(user, amount) for outbound. function burnFrom(address from, uint256 amount) external onlyRole(BURNER_ROLE) { _burn(from, amount); } }