Yield-Convex contest - throttle's results

Fixed-rate borrowing and lending on Ethereum

General Information

Platform: Code4rena

Start Date: 28/01/2022

Pot Size: $30,000 USDC

Total HM: 4

Participants: 22

Period: 3 days

Judge: GalloDaSballo

Total Solo HM: 2

Id: 80

League: ETH

Yield

Findings Distribution

Researcher Performance

Rank: 10/22

Findings: 3

Award: $167.73

🌟 Selected for report: 1

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: throttle

Also found by: 0x1f8b, TomFrenchBlockchain, WatchPug, cccz, defsec, hack3r-0m, hyh, kenzo, leastwood, sirhashalot, ye0lde

Labels

bug
2 (Med Risk)
resolved
sponsor confirmed

Awards

69.1238 USDC - $69.12

External Links

Handle

throttle

Vulnerability details

Impact

Price can be stale and can lead to wrong quoteAmount return value

Proof of Concept

Oracle data feed is insufficiently validated. There is no check for stale price and round completeness. Price can be stale and can lead to wrong quoteAmount return value

function _peek(
    bytes6 base,
    bytes6 quote,
    uint256 baseAmount
) private view returns (uint256 quoteAmount, uint256 updateTime) {
    ...

    (, int256 daiPrice, , , ) = DAI.latestRoundData();
    (, int256 usdcPrice, , , ) = USDC.latestRoundData();
    (, int256 usdtPrice, , , ) = USDT.latestRoundData();

    require(
        daiPrice > 0 && usdcPrice > 0 && usdtPrice > 0,
        "Chainlink pricefeed reporting 0"
    );

    ...
}

Tools Used

Manual review

Validate data feed

function _peek(
    bytes6 base,
    bytes6 quote,
    uint256 baseAmount
) private view returns (uint256 quoteAmount, uint256 updateTime) {
    ...
    (uint80 roundID, int256 daiPrice, , uint256 timestamp, uint80 answeredInRound) = DAI.latestRoundData();
    require(daiPrice > 0, "ChainLink: DAI price <= 0");
    require(answeredInRound >= roundID, "ChainLink: Stale price");
    require(timestamp > 0, "ChainLink: Round not complete");

    (roundID, int256 usdcPrice, , timestamp, answeredInRound) = USDC.latestRoundData();
    require(usdcPrice > 0, "ChainLink: USDC price <= 0");
    require(answeredInRound >= roundID, "ChainLink: Stale USDC price");
    require(timestamp > 0, "ChainLink: USDC round not complete");

    (roundID, int256 usdtPrice, , timestamp, answeredInRound) = USDT.latestRoundData();
    require(usdtPrice > 0, "ChainLink: USDT price <= 0");
    require(answeredInRound >= roundID, "ChainLink: Stale USDT price");
    require(timestamp > 0, "ChainLink: USDT round not complete");

    ...
}

#0 - GalloDaSballo

2022-02-14T22:33:14Z

When using Chainlink Price feeds it is important to ensure the price feed data was updated recently. While getting started with chainlink requires just one line of code, it is best to add additional checks for in production environments.

I believe the finding to be valid and Medium severity to be appropriate.

The sponsor has mitigated in a subsequent PR

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