prove with evidence this issue pon diligent review of the OLAS smart contract, a potential vulnerability within the mint function becomes noticeable due to a discrepancy in the logic designed to enforce the token’s supply cap and inflation controls.

### Potential Vulnerability: Ineffective Inflation Control in Minting Process ###

Vulnerable Code:


function mint(address account, uint256 amount) external {
    // Access control
    if (msg.sender != minter) {
        revert ManagerOnly(msg.sender, minter);
    }

    // Check the inflation schedule and mint
    if (inflationControl(amount)) {
        _mint(account, amount);
    }
}



Vulnerability Description:
The mint function includes a check to ensure minting requests are within the allowed inflation boundaries by consulting the inflationControl function. However, it neither reverts nor indicates a problem if the inflationControl returns false. It simply skips the _mint operation silently. This could cause confusion and inconsistency in the expected behavior of the mint function.

Although this isn’t a direct vulnerability that risks funds or the integrity of the contract state, it’s a logical flaw that could impact the intended economics by allowing minting without properly signaling failure when inflation control checks fail.

Hypothetical Exploit Scenario:
A user (or minter) trying to mint tokens interacts with the mint method and passes an amount that exceeds the current supply cap permitted by the inflationRemainder. Due to the lack of explicit failure notification, the user receives no tokens but is not informed that the operation was blocked due to inflation controls.

This could lead to confusion and result in repeated transactions by the user attempting to mint, costing unnecessary gas usage without successful token generation. While the contract’s funds and state aren’t directly at risk, this logic flaw can negatively impact user experience and the intended token economics of the system.

Recommendation:
An explicit revert should occur within the mint function if the inflationControl returns false, to clearly indicate the operation has exceeded the allowed inflation bounds:


function mint(address account, uint256 amount) external {
    // Access control
    if (msg.sender != minter) {
        revert ManagerOnly(msg.sender, minter);
    }

    // Ensure minting is within the inflation bounds before proceeding
    if (!inflationControl(amount)) {
        revert SomeErrorExceedingInflationBound();
    }

    _mint(account, amount);
}



Evidence:
The evidence is derived from the logical flow within the code itself, where the failure to mint due to inflation constraints does not revert the transaction or provide feedback.

Severity:
Medium - The contract does not risk unexpected minting beyond the inflation control, but lacks proper error handling and feedback, leading to a potentially poor user experience and unclear behavior.

High-Quality Bug Report:

- Summary: Ineffective Inflation Control in Minting Process.
- Severity: Medium.
- Vulnerable Part: The mint function will silently fail to mint tokens without properly indicating the failure when the requested amount exceeds the inflation control checks.
- Impact: Could lead to confusion among minters when tokens aren’t minted and no clear failure notification is provided, undermining the clarity of the minting functionality.
- Recommendation: Modify the mint function to include a revert with a clear error message when the inflation control check fails.
- Proof of Vulnerability: The logical flow of the mint function when inflationControl returns false, which currently skips minting but does not revert or generate a failure event.

This evaluation is based on the code provided and is not a substitute for a comprehensive security audit. If this were a real-world scenario, testers would also need to consider the contract’s deployment context, its interactions with other contracts, and the broader ecosystem in which it operates. is present ini this contract // SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;

import "../lib/solmate/src/tokens/ERC20.sol";

/// @dev Only `manager` has a privilege, but the `sender` was provided.
/// @param sender Sender address.
/// @param manager Required sender address as a manager.
error ManagerOnly(address sender, address manager);

/// @dev Provided zero address.
error ZeroAddress();

/// @title OLAS - Smart contract for the OLAS token.
/// @author AL
/// @author Aleksandr Kuperman - <aleksandr.kuperman@valory.xyz>
contract OLAS is ERC20 {
    event MinterUpdated(address indexed minter);
    event OwnerUpdated(address indexed owner);

    // One year interval
    uint256 public constant oneYear = 1 days * 365;
    // Total supply cap for the first ten years (one billion OLAS tokens)
    uint256 public constant tenYearSupplyCap = 1_000_000_000e18;
    // Maximum annual inflation after first ten years
    uint256 public constant maxMintCapFraction = 2;
    // Initial timestamp of the token deployment
    uint256 public immutable timeLaunch;

    // Owner address
    address public owner;
    // Minter address
    address public minter;

    constructor() ERC20("Autonolas", "OLAS", 18) {
        owner = msg.sender;
        minter = msg.sender;
        timeLaunch = block.timestamp;
    }

    /// @dev Changes the owner address.
    /// @param newOwner Address of a new owner.
    function changeOwner(address newOwner) external {
        if (msg.sender != owner) {
            revert ManagerOnly(msg.sender, owner);
        }

        if (newOwner == address(0)) {
            revert ZeroAddress();
        }

        owner = newOwner;
        emit OwnerUpdated(newOwner);
    }

    /// @dev Changes the minter address.
    /// @param newMinter Address of a new minter.
    function changeMinter(address newMinter) external {
        if (msg.sender != owner) {
            revert ManagerOnly(msg.sender, owner);
        }

        if (newMinter == address(0)) {
            revert ZeroAddress();
        }

        minter = newMinter;
        emit MinterUpdated(newMinter);
    }

    /// @dev Mints OLAS tokens.
    /// @notice If the inflation control does not pass, the revert does not take place, as well as no action is performed.
    /// @param account Account address.
    /// @param amount OLAS token amount.
    function mint(address account, uint256 amount) external {
        // Access control
        if (msg.sender != minter) {
            revert ManagerOnly(msg.sender, minter);
        }

        // Check the inflation schedule and mint
        if (inflationControl(amount)) {
            _mint(account, amount);
        }
    }

    /// @dev Provides various checks for the inflation control.
    /// @notice The `<=` check is left as is for a better code readability.
    /// @param amount Amount of OLAS to mint.
    /// @return True if the amount request is within inflation boundaries.
    function inflationControl(uint256 amount) public view returns (bool) {
        uint256 remainder = inflationRemainder();
        return (amount <= remainder);
    }

    /// @dev Gets the reminder of OLAS possible for the mint.
    /// @return remainder OLAS token remainder.
    function inflationRemainder() public view returns (uint256 remainder) {
        uint256 _totalSupply = totalSupply;
        // Current year
        uint256 numYears = (block.timestamp - timeLaunch) / oneYear;
        // Calculate maximum mint amount to date
        uint256 supplyCap = tenYearSupplyCap;
        // After 10 years, adjust supplyCap according to the yearly inflation % set in maxMintCapFraction
        if (numYears > 9) {
            // Number of years after ten years have passed (including ongoing ones)
            numYears -= 9;
            for (uint256 i = 0; i < numYears; ++i) {
                supplyCap += (supplyCap * maxMintCapFraction) / 100;
            }
        }
        // Check for the requested mint overflow
        remainder = supplyCap - _totalSupply;
    }

    /// @dev Burns OLAS tokens.
    /// @param amount OLAS token amount to burn.
    function burn(uint256 amount) external {
        _burn(msg.sender, amount);
    }

    /// @dev Decreases the allowance of another account over their tokens.
    /// @notice This implementation does not decrease spender allowance if the maximum allowance was granted.
    /// @notice The underflow condition is treated by the default code generation check.
    /// @param spender Account that tokens are approved for.
    /// @param amount Amount to decrease approval by.
    /// @return True if the operation succeeded.
    function decreaseAllowance(address spender, uint256 amount) external returns (bool) {
        uint256 spenderAllowance = allowance[msg.sender][spender];

        if (spenderAllowance != type(uint256).max) {
            spenderAllowance -= amount;
            allowance[msg.sender][spender] = spenderAllowance;
            emit Approval(msg.sender, spender, spenderAllowance);
        }

        return true;
    }

    /// @dev Increases the allowance of another account over their tokens.
    /// @notice The overflow condition is treated by the default code generation check.
    /// @param spender Account that tokens are approved for.
    /// @param amount Amount to increase approval by.
    /// @return True if the operation succeeded.
    function increaseAllowance(address spender, uint256 amount) external returns (bool) {
        uint256 spenderAllowance = allowance[msg.sender][spender];

        spenderAllowance += amount;
        allowance[msg.sender][spender] = spenderAllowance;
        emit Approval(msg.sender, spender, spenderAllowance);

        return true;
    }
}