code-423n4 / 2024-05-olas-validation

0 stars 0 forks source link

No access control in "initializeTokenomics" in Tokenomics.sol. #248

Open c4-bot-4 opened 4 months ago

c4-bot-4 commented 4 months ago

Lines of code

https://github.com/code-423n4/2024-05-olas/blob/main/tokenomics/contracts/Tokenomics.sol#L409

Vulnerability details

Impact

Detailed description of the impact of this finding. In initializeTokenomics function there is no access control as anyone calls and inilize this function.

Proof of Concept

Provide direct links to all referenced code in GitHub. Add screenshots, logs, or any other relevant proof that illustrates the concept. function initializeTokenomics( address _olas, address _treasury, address _depository, address _dispenser, address _ve, uint256 _epochLen, address _componentRegistry, address _agentRegistry, address _serviceRegistry, address _donatorBlacklist ) external { // Check if the contract is already initialized if (owner != address(0)) { revert AlreadyInitialized(); }

    // Check for at least one zero contract address
    if (_olas == address(0) || _treasury == address(0) || _depository == address(0) || _dispenser == address(0) ||
        _ve == address(0) || _componentRegistry == address(0) || _agentRegistry == address(0) ||
        _serviceRegistry == address(0)) {
        revert ZeroAddress();
    }

    // Initialize storage variables
    owner = msg.sender;
    _locked = 1;
    epsilonRate = 1e17;
    veOLASThreshold = 10_000e18;

    // Check that the epoch length has at least a practical minimal value
    if (uint32(_epochLen) < MIN_EPOCH_LENGTH) {
        revert LowerThan(_epochLen, MIN_EPOCH_LENGTH);
    }

    // Check that the epoch length is not out of defined bounds
    if (uint32(_epochLen) > MAX_EPOCH_LENGTH) {
        revert Overflow(_epochLen, MAX_EPOCH_LENGTH);
    }

    // Assign other input variables
    olas = _olas;
    treasury = _treasury;
    depository = _depository;
    dispenser = _dispenser;
    ve = _ve;
    epochLen = uint32(_epochLen);
    componentRegistry = _componentRegistry;
    agentRegistry = _agentRegistry;
    serviceRegistry = _serviceRegistry;
    donatorBlacklist = _donatorBlacklist;

    // Time launch of the OLAS contract
    uint256 _timeLaunch = IOLAS(_olas).timeLaunch();
    // Check that the tokenomics contract is initialized no later than one year after the OLAS token is deployed
    if (block.timestamp >= (_timeLaunch + ONE_YEAR)) {
        revert Overflow(_timeLaunch + ONE_YEAR, block.timestamp);
    }
    // Seconds left in the deployment year for the zero year inflation schedule
    // This value is necessary since it is different from a precise one year time, as the OLAS contract started earlier
    uint256 zeroYearSecondsLeft = uint32(_timeLaunch + ONE_YEAR - block.timestamp);
    // Calculating initial inflation per second: (mintable OLAS from getInflationForYear(0)) / (seconds left in a year)
    // Note that we lose precision here dividing by the number of seconds right away, but to avoid complex calculations
    // later we consider it less error-prone and sacrifice at most 6 insignificant digits (or 1e-12) of OLAS per year
    uint256 _inflationPerSecond = getInflationForYear(0) / zeroYearSecondsLeft;
    inflationPerSecond = uint96(_inflationPerSecond);
    timeLaunch = uint32(_timeLaunch);

    // The initial epoch start time is the end time of the zero epoch
    mapEpochTokenomics[0].epochPoint.endTime = uint32(block.timestamp);

    // The epoch counter starts from 1
    epochCounter = 1;
    TokenomicsPoint storage tp = mapEpochTokenomics[1];

    // Setting initial parameters and fractions
    devsPerCapital = 1e18;
    tp.epochPoint.idf = 1e18;

    // Reward fractions
    // 0 stands for components and 1 for agents
    tp.unitPoints[0].rewardUnitFraction = 83;
    tp.unitPoints[1].rewardUnitFraction = 17;
    // tp.epochPoint.rewardTreasuryFraction is essentially equal to zero

    // We consider a unit of code as n agents or m components.
    // Initially we consider 1 unit of code as either 2 agents or 1 component.
    // E.g. if we have 2 profitable components and 2 profitable agents, this means there are (2 x 2.0 + 2 x 1.0) / 3 = 2
    // units of code.
    // We assume that during one epoch the developer can contribute with one piece of code (1 component or 2 agents)
    codePerDev = 1e18;

    // Top-up fractions
    uint256 _maxBondFraction = 50;
    tp.epochPoint.maxBondFraction = uint8(_maxBondFraction);
    tp.unitPoints[0].topUpUnitFraction = 41;
    tp.unitPoints[1].topUpUnitFraction = 9;

    // Calculate initial effectiveBond based on the maxBond during the first epoch
    // maxBond = inflationPerSecond * epochLen * maxBondFraction / 100
    uint256 _maxBond = (_inflationPerSecond * _epochLen * _maxBondFraction) / 100;
    maxBond = uint96(_maxBond);
    effectiveBond = uint96(_maxBond);
}

Tools Used

Recommended Mitigation Steps

we should define a variable inilized to false earlier and then inilized true in initializeTokenomics.so that no one can call again.

Assessed type

Access Control