Olas - HChang26's results

Olas is a unified network for off-chain services like automation, oracles, co-owned AI. It offers a stack for building services and a protocol for incentivizing their creation and their operation in a co-owned and decentralized way.

General Information

Platform: Code4rena

Start Date: 21/12/2023

Pot Size: $90,500 USDC

Total HM: 10

Participants: 39

Period: 18 days

Judge: LSDan

Total Solo HM: 5

Id: 315

League: ETH

Olas

Findings Distribution

Researcher Performance

Rank: 6/39

Findings: 1

Award: $830.39

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: hash

Also found by: 0xTheC0der, HChang26, c0pp3rscr3w3r

Labels

bug
3 (High Risk)
partial-50
sufficient quality report
upgraded by judge
duplicate-373

Awards

830.3941 USDC - $830.39

External Links

Lines of code

https://github.com/code-423n4/2023-12-autonolas/blob/main/governance/contracts/OLAS.sol#L75 https://github.com/code-423n4/2023-12-autonolas/blob/main/tokenomics/contracts/Dispenser.sol#L89 https://github.com/code-423n4/2023-12-autonolas/blob/main/tokenomics/contracts/Tokenomics.sol#L1085 https://github.com/code-423n4/2023-12-autonolas/blob/main/tokenomics/contracts/Treasury.sol#L387

Vulnerability details

Impact

The claimOwnerIncentives() function may lead users to potentially lose their deserved topUps due to a silent failure in the mint() function, constrained by inflation control.

Proof of Concept

Within the claimOwnerIncentives() function, the accountOwnerIncentives() on Tokenomics.sol is invoked when users claim their incentives. This function aggregates total rewards and top-ups and subsequently resets their balances.

        for (uint256 i = 0; i < unitIds.length; ++i) {
            // Get the last epoch number the incentives were accumulated for
            uint256 lastEpoch = mapUnitIncentives[unitTypes[i]][unitIds[i]].lastEpoch;
            // Finalize unit rewards and top-ups if there were pending ones from the previous epoch
            // The finalization is needed when the trackServiceDonations() function did not take care of it
            // since between last epoch the donations were received and this current epoch there were no more donations
            if (lastEpoch > 0 && lastEpoch < curEpoch) {
                _finalizeIncentivesForUnitId(lastEpoch, unitTypes[i], unitIds[i]);
                // Change the last epoch number
                mapUnitIncentives[unitTypes[i]][unitIds[i]].lastEpoch = 0;
            }

            // Accumulate total rewards and clear their balances
            reward += mapUnitIncentives[unitTypes[i]][unitIds[i]].reward;
            mapUnitIncentives[unitTypes[i]][unitIds[i]].reward = 0;
            // Accumulate total top-ups and clear their balances
            topUp += mapUnitIncentives[unitTypes[i]][unitIds[i]].topUp;
            mapUnitIncentives[unitTypes[i]][unitIds[i]].topUp = 0;
        }

The accumulated reward and topUp values from accountOwnerIncentives() trigger the withdrawToAccount() function in the treasury. This function manages ETH distribution and OLAS token minting.

        if (accountTopUps > 0) {
            IOLAS(olas).mint(account, accountTopUps);
            success = true;
            emit Withdraw(olas, account, accountTopUps);
        }

The potential issue arises from the mint() function's ability to silently fail without triggering a revert. This occurs as OLAS verifies against inflationControl() and only executes minting when the function returns true.

    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);
        }
    }

WithdrawToAccount() returning true and the system acknowledging successful receipt of entitled topUps while resetting the topUp balance to 0, the silent failure in mint() may lead to users missing their rightful topUps.

Tools Used

Manual Review

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

Assessed type

Context

#0 - c4-pre-sort

2024-01-10T15:07:02Z

alex-ppg marked the issue as duplicate of #390

#1 - c4-pre-sort

2024-01-10T15:07:06Z

alex-ppg marked the issue as sufficient quality report

#2 - c4-judge

2024-01-20T13:01:08Z

dmvt marked the issue as satisfactory

#3 - c4-judge

2024-01-23T12:44:10Z

dmvt marked the issue as duplicate of #373

#4 - c4-judge

2024-01-23T12:45:32Z

dmvt changed the severity to 3 (High Risk)

#5 - c4-judge

2024-01-23T12:45:36Z

dmvt marked the issue as partial-50

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter