// SPDX-License-Identifier: MIT pragma solidity 0.8.15; import "@openzeppelin/contracts/access/Ownable.sol"; import "./GovernanceToken.sol"; /// @title MintManager /// @notice Set as `owner` of the governance token and responsible for the token inflation /// schedule. Contract acts as the token "mint manager" with permission to the `mint` /// function only. Currently permitted to mint once per year of up to 2% of the total /// token supply. Upgradable to allow changes in the inflation schedule. contract MintManager is Ownable { /// @notice The GovernanceToken that the MintManager can mint tokens GovernanceToken public immutable governanceToken; /// @notice The amount of tokens that can be minted per year. /// The value is a fixed point number with 4 decimals. uint256 public constant MINT_CAP = 20; // 2% /// @notice The number of decimals for the MINT_CAP. uint256 public constant DENOMINATOR = 1000; /// @notice The amount of time that must pass before the MINT_CAP number of tokens can /// be minted again. uint256 public constant MINT_PERIOD = 365 days; /// @notice Tracks the time of last mint. uint256 public mintPermittedAfter; /// @notice Constructs the MintManager contract. /// @param _upgrader The owner of this contract. /// @param _governanceToken The governance token this contract can mint tokens of. constructor(address _upgrader, address _governanceToken) { transferOwnership(_upgrader); governanceToken = GovernanceToken(_governanceToken); } /// @notice Only the token owner is allowed to mint a certain amount of the /// governance token per year. /// @param _account The account receiving minted tokens. /// @param _amount The amount of tokens to mint. function mint(address _account, uint256 _amount) public onlyOwner { if (mintPermittedAfter > 0) { require(mintPermittedAfter <= block.timestamp, "MintManager: minting not permitted yet"); require( _amount <= (governanceToken.totalSupply() * MINT_CAP) / DENOMINATOR, "MintManager: mint amount exceeds cap" ); } mintPermittedAfter = block.timestamp + MINT_PERIOD; governanceToken.mint(_account, _amount); } /// @notice Upgrade the owner of the governance token to a new MintManager. /// @param _newMintManager The MintManager to upgrade to. function upgrade(address _newMintManager) public onlyOwner { require(_newMintManager != address(0), "MintManager: mint manager cannot be the zero address"); governanceToken.transferOwnership(_newMintManager); } }