// contracts/GLDToken.sol // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { ERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol"; import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; /// @title EspToken /// @notice ERC20 token for the Espresso network, upgradeable via UUPS. /// @dev Upgradeability & storage layout (frozen-inheritance pattern) /// We intentionally do not use `__gap` slots. Once a version is deployed, /// its storage layout is frozen and never modified. New state variables are /// added only in a new child contract (V2, V3, …) that inherits from the /// previous version and appends fields at the end. This preserves slot order /// across upgrades without relying on gaps. (Note: upstream OZ parents may /// include their own gaps—those remain untouched.) contract EspToken is Initializable, ERC20Upgradeable, OwnableUpgradeable, UUPSUpgradeable { /// @notice Cannot renounce ownership error OwnershipCannotBeRenounced(); /// @notice since the constructor initializes storage on this contract we disable it /// @dev storage is on the proxy contract since it calls this contract via delegatecall /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } /// @notice This contract is called by the proxy when you deploy this contract function initialize( address owner, address initialRecipient, uint256 initialSupply, string memory name, string memory symbol ) public initializer { __ERC20_init(name, symbol); __Ownable_init(owner); __UUPSUpgradeable_init(); initialSupply = initialSupply * 10 ** decimals(); _mint(initialRecipient, initialSupply); } /// @notice only the owner can authorize an upgrade // solhint-disable-next-line no-empty-blocks function _authorizeUpgrade(address newImplementation) internal virtual override onlyOwner { } /// @notice Cannot renounce ownership /// @dev Override renounceOwnership() to revert, preventing accidental or malicious ownership /// renunciation function renounceOwnership() public virtual override onlyOwner { revert OwnershipCannotBeRenounced(); } /// @notice Use this to get the implementation contract version function getVersion() public pure virtual returns (uint8 majorVersion, uint8 minorVersion, uint8 patchVersion) { return (1, 0, 0); } }