// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

/**
 * @title AereBridgedToken — generic bridged-asset token for AERE Warp Routes
 * @notice One contract, many stablecoins. Replaces the USDC.e-only USDCe.sol
 *         with a parameterised version so that USDT.e, USDe.e, EURC.e (and
 *         future bridged assets) share the same audited bytecode.
 *
 *         The corresponding AereHypERC20Synthetic on AERE is set immutably
 *         at construction and is the SOLE address that can mint or burn.
 *         No admin, no pauser, no blacklist — those features add attack
 *         surface and we publish reserve commitments via AereNavOracle
 *         instead.
 *
 *         Decimal handling: each constituent stablecoin keeps its native
 *         decimal count (USDC.e, USDT.e, EURC.e: 6 ; USDe.e: 18). The
 *         decimals are an immutable constructor arg, not OZ's default 18.
 *
 *         AUDIT NOTE: identical surface area to USDCe.sol; same audit
 *         reasoning applies. The only change is parametric name/symbol/
 *         decimals. Both contracts can coexist on chain — USDC.e remains
 *         pointing at the deployed USDCe.sol instance for historical
 *         continuity; new stables use AereBridgedToken.
 */
contract AereBridgedToken is ERC20 {
    /// @notice The one and only contract authorised to mint or burn.
    address public immutable BRIDGE;
    /// @notice Decimal count, captured immutably at deploy.
    uint8 private immutable _DECIMALS;

    error OnlyBridge();

    modifier onlyBridge() {
        if (msg.sender != BRIDGE) revert OnlyBridge();
        _;
    }

    constructor(string memory name_, string memory symbol_, uint8 decimals_, address bridge_)
        ERC20(name_, symbol_)
    {
        require(bridge_ != address(0), "AereBridgedToken: zero bridge");
        BRIDGE = bridge_;
        _DECIMALS = decimals_;
    }

    function decimals() public view override returns (uint8) {
        return _DECIMALS;
    }

    function mint(address to, uint256 amount) external onlyBridge {
        _mint(to, amount);
    }

    /// AUDIT FIX (HIGH #15): even though BRIDGE is the only authorised caller,
    /// require the user to have explicitly approved the bridge for the burn
    /// amount. A bridge bug / compromise can no longer wipe arbitrary balances
    /// — only what users explicitly allowed.
    function burnFrom(address from, uint256 amount) external onlyBridge {
        if (from != msg.sender) {
            _spendAllowance(from, msg.sender, amount);
        }
        _burn(from, amount);
    }
}
