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

QA Report #190

Open
code423n4 opened this issue Jun 19, 2022 · 6 comments
Open

QA Report #190

code423n4 opened this issue Jun 19, 2022 · 6 comments
Labels
bug Something isn't working QA (Quality Assurance) Assets are not at risk. State handling, function incorrect as to spec, issues with clarity, syntax sponsor confirmed Sponsor agrees this is a problem and intends to fix it (OK to use w/ "disagree with severity")

Comments

@code423n4
Copy link
Contributor

code423n4 commented Jun 19, 2022

Chainlink oracle aggregator data is insufficiently validated in ConnextPriceOracle.sol

Lines of code

https://github.com/code-423n4/2022-06-connext/blob/b4532655071566b33c41eac46e75be29b4a381ed/contracts/contracts/core/connext/helpers/ConnextPriceOracle.sol#L122-L140

Vulnerability details

Impact

The function getPriceFromChainlink() in ConnextPriceOracle.sol fetches the latestRoundData() from a registered aggregator (Chainlink oracle feed) for a specified token. However, neither round completeness or the quoted timestamp are checked to ensure that the reported price is not stale.

Since Connext is creating bridged representations of tokens from other chains, it is vital for the reported prices of tokens to be accurate. While Connext also consults the DEX reported price of the tokens, some pairs with thin liquidity could also return inaccurate prices.

Proof of Concept

function getPriceFromChainlink(address _tokenAddress) public view returns (uint256) {
    AggregatorV3Interface aggregator = aggregators[_tokenAddress];
    if (address(aggregator) != address(0)) {
      (, int256 answer, , , ) = aggregator.latestRoundData();

      // It's fine for price to be 0. We have two price feeds.
      if (answer == 0) {
        return 0;
      }

      // Extend the decimals to 1e18.
      uint256 retVal = uint256(answer);
      uint256 price = retVal.mul(10**(18 - uint256(aggregator.decimals())));

      return price;
    }

    return 0;
  }

Note that the other returned variables roundId, startedAt, updatedAt, and answeredInRound are omitted from the return result of aggregator.latestRoundData().

Mitigation steps

Add additional validation:

    ...
     (uint80 roundID, int256 price, , uint256 updatedAt, uint80 answeredInRound) = aggregator.latestRoundData();
    require(answeredInRound >= roundID, "ChainLink: Stale price");
    require(updatedAt != 0, "ChainLink: Round not complete");
    ...

Tools Used

Manual review

@jakekidd
Copy link
Collaborator

best description of issue with mitigation step here :)

@0xleastwood
Copy link
Collaborator

While the issue is valid, this particular part of the codebase is not in active use, however, it may be used in the future. It would make sense to downgrade this to QA.

@0xleastwood 0xleastwood changed the title Chainlink oracle aggregator data is insufficiently validated in ConnextPriceOracle.sol QA Report Aug 12, 2022
@0xleastwood 0xleastwood added 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 Aug 12, 2022
@IllIllI000
Copy link

@0xleastwood what makes you say that it's not in active use? The readme shows how it's being used https://github.com/code-423n4/2022-06-connext/tree/main/contracts#how-to-set-price-information-in-connextpriceoracle

@0xleastwood
Copy link
Collaborator

https://github.com/code-423n4/2022-06-connext/tree/main/contracts#how-to-set-price-information-in-connextpriceoracle

Can you find me an example where this is being used anywhere in the bridge transfer logic?

@IllIllI000
Copy link

https://github.com/code-423n4/2022-06-connext/tree/main/contracts#how-to-set-price-information-in-connextpriceoracle

Can you find me an example where this is being used anywhere in the bridge transfer logic?

It's deployed along with everything else https://github.com/code-423n4/2022-06-connext/blob/4dd6149748b635f95460d4c3924c7e3fb6716967/contracts/deploy/02_deployConnext.ts#L159 are you really trying to claim that if two pieces don't directly interact, that you can arbitrarily downgrade any finding in one of them?

@0xleastwood
Copy link
Collaborator

https://github.com/code-423n4/2022-06-connext/blob/4dd6149748b635f95460d4c3924c7e3fb6716967/contracts/deploy/02_deployConnext.ts#L159

It's being deployed but not used anywhere. I've spoken to the team about this and they may potentially use the contracts in the future but for now that's not the case. Context matters when determining the severity of an issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working QA (Quality Assurance) Assets are not at risk. State handling, function incorrect as to spec, issues with clarity, syntax sponsor confirmed Sponsor agrees this is a problem and intends to fix it (OK to use w/ "disagree with severity")
Projects
None yet
Development

No branches or pull requests

4 participants