Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BalancerOracle::update() can return stale price #124

Open
howlbot-integration bot opened this issue Aug 20, 2024 · 8 comments
Open

BalancerOracle::update() can return stale price #124

howlbot-integration bot opened this issue Aug 20, 2024 · 8 comments
Labels
2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value bug Something isn't working M-28 primary issue Highest quality submission among a set of duplicates 🤖_32_group AI based duplicate group recommendation satisfactory satisfies C4 submission criteria; eligible for awards selected for report This submission will be included/highlighted in the audit report sponsor acknowledged Technically the issue is correct, but we're not going to resolve it for XYZ reasons sufficient quality report This report is of sufficient quality

Comments

@howlbot-integration
Copy link

Lines of code

https://github.com/code-423n4/2024-07-loopfi/blob/57871f64bdea450c1f04c9a53dc1a78223719164/src/oracle/BalancerOracle.sol#L114-L136

Vulnerability details

Impact

Whenever block.timestamp - lastUpdate > updateWaitWindow and needs to update the price it will return a stale price because it will fetch the price from the lastUpdate not the currentUpdate.

Proof of Concept

In the update() function these are the lines we'll find

 //@audit lets say price is out of date and its getting updated won't it get the pric from one hour ago?
//problem is it uses a current timestamp but with an hour old price
        if (block.timestamp - lastUpdate < updateWaitWindow) revert BalancerOracle__update_InUpdateWaitWindow();
        // update the safe price first
        safePrice = safePrice_ = currentPrice;
        lastUpdate = block.timestamp;

        uint256[] memory weights = IWeightedPool(pool).getNormalizedWeights();
        uint256 totalSupply = IWeightedPool(pool).totalSupply();

        uint256 totalPi = WAD;
        uint256[] memory prices = new uint256[](weights.length);
        // update balances in 18 decimals
        for (uint256 i = 0; i < weights.length; i++) {
            // reverts if the price is invalid or stale
            prices[i] = _getTokenPrice(i);
            uint256 val = wdiv(prices[i], weights[i]);
            uint256 indivPi = uint256(wpow(int256(val), int256(weights[i])));

            totalPi = wmul(totalPi, indivPi);
        }

        currentPrice = wdiv(wmul(totalPi, IWeightedPool(pool).getInvariant()), totalSupply);

from the code we can see that the currentPrice is the last thing updated.

and whenever there updateWindow reaches or passes for us to fetch a new price the safePrice is updated first which is the value from the lastUpdate which is "stale".

it can be argued that its a design decision meaning the updateWindow is just time it needs to fetch a new price but it doesn't mean the price is old. However the updateWindow can be passed and not updated right after meaning the price is two times back because it wasn't updated right away.

Tools Used

manual review

Recommended Mitigation Steps

Revisit the logic to be able to fetch fresh price whenever there need to be a new price fetched

Assessed type

Oracle

@howlbot-integration howlbot-integration bot added 2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value 🤖_32_group AI based duplicate group recommendation bug Something isn't working primary issue Highest quality submission among a set of duplicates sufficient quality report This report is of sufficient quality labels Aug 20, 2024
howlbot-integration bot added a commit that referenced this issue Aug 20, 2024
@0xtj24 0xtj24 self-assigned this Aug 24, 2024
@c4-sponsor
Copy link

@0xtj24 Sponsors are not allowed to close, reopen, or assign issues or pull requests.

@0xtj24
Copy link

0xtj24 commented Sep 10, 2024

That logic updates the price only after a certain updateWaitWindow has passed, storing the oldest safe price. If not updated with the keeper it will return stale price depending on the stalePeriod. This is an expected behaviour

@0xtj24 0xtj24 added the sponsor acknowledged Technically the issue is correct, but we're not going to resolve it for XYZ reasons label Sep 10, 2024
@c4-judge c4-judge added downgraded by judge Judge downgraded the risk level of this issue QA (Quality Assurance) Assets are not at risk. State handling, function incorrect as to spec, issues with clarity, syntax and removed 2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value labels Oct 1, 2024
@c4-judge
Copy link
Contributor

c4-judge commented Oct 1, 2024

koolexcrypto changed the severity to QA (Quality Assurance)

@c4-judge c4-judge closed this as completed Oct 1, 2024
@c4-judge c4-judge added grade-c unsatisfactory does not satisfy C4 submission criteria; not eligible for awards labels Oct 1, 2024
@c4-judge
Copy link
Contributor

c4-judge commented Oct 1, 2024

koolexcrypto marked the issue as grade-c

@c4-judge
Copy link
Contributor

This previously downgraded issue has been upgraded by koolexcrypto

@c4-judge c4-judge reopened this Oct 13, 2024
@c4-judge c4-judge added 2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value and removed downgraded by judge Judge downgraded the risk level of this issue QA (Quality Assurance) Assets are not at risk. State handling, function incorrect as to spec, issues with clarity, syntax labels Oct 13, 2024
@koolexcrypto
Copy link

Since updateWaitWindow is immutable, it can't be changed. Therefore, upgrading the severity to Med again.

@c4-judge
Copy link
Contributor

koolexcrypto marked the issue as satisfactory

@c4-judge c4-judge added satisfactory satisfies C4 submission criteria; eligible for awards and removed grade-c unsatisfactory does not satisfy C4 submission criteria; not eligible for awards labels Oct 13, 2024
@c4-judge c4-judge added the selected for report This submission will be included/highlighted in the audit report label Oct 13, 2024
@c4-judge
Copy link
Contributor

koolexcrypto marked the issue as selected for report

@C4-Staff C4-Staff added the M-28 label Nov 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value bug Something isn't working M-28 primary issue Highest quality submission among a set of duplicates 🤖_32_group AI based duplicate group recommendation satisfactory satisfies C4 submission criteria; eligible for awards selected for report This submission will be included/highlighted in the audit report sponsor acknowledged Technically the issue is correct, but we're not going to resolve it for XYZ reasons sufficient quality report This report is of sufficient quality
Projects
None yet
Development

No branches or pull requests

5 participants