Inverse Finance contest - eierina's results

Rethink the way you borrow.

General Information

Platform: Code4rena

Start Date: 25/10/2022

Pot Size: $50,000 USDC

Total HM: 18

Participants: 127

Period: 5 days

Judge: 0xean

Total Solo HM: 9

Id: 175

League: ETH

Inverse Finance

Findings Distribution

Researcher Performance

Rank: 46/127

Findings: 3

Award: $58.23

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

Awards

33.634 USDC - $33.63

Labels

bug
2 (Med Risk)
satisfactory
edited-by-warden
duplicate-301

External Links

Lines of code

https://github.com/code-423n4/2022-10-inverse/blob/3e81f0f5908ea99b36e6ab72f13488bbfe622183/src/Market.sol#L136

Vulnerability details

Impact

A lender may be swapped out by governance at any time, or by enough voting power, depending on the governance implementation, without returning the free and/or borrowed balance to the lender. If a single or a group may benefit from it, then there should be measures to prevent it.

Proof of Concept

https://github.com/code-423n4/2022-10-inverse/blob/3e81f0f5908ea99b36e6ab72f13488bbfe622183/src/Market.sol#L136

Tools Used

n/a

As a minimum I would expect something like the following: gov proposes new lender, old lender executes/finalize the swap in a way that arrangements between the two lenders can be settled outside of the market. This works also in the case the new lender and old lender are owned by same entity.

While the external agreement takes place (or not)

  • new borrowings are paused until swap completes
  • free dola balance are recalled from market to the lender
  • new lender can execute the swap if all borrowings are repaid or liquidated and old lender does not execute the swap itself (e.g. external agreement not reached)

#0 - c4-judge

2022-11-05T22:53:16Z

0xean marked the issue as duplicate

#1 - Simon-Busch

2022-12-05T15:36:54Z

Issue marked as satisfactory as requested by 0xean

#2 - c4-judge

2022-12-07T08:22:05Z

Simon-Busch marked the issue as duplicate of #301

Findings Information

Awards

24.2165 USDC - $24.22

Labels

bug
2 (Med Risk)
satisfactory
edited-by-warden
duplicate-533

External Links

Lines of code

https://github.com/code-423n4/2022-10-inverse/blob/3e81f0f5908ea99b36e6ab72f13488bbfe622183/src/Oracle.sol#L87-L88 https://github.com/code-423n4/2022-10-inverse/blob/3e81f0f5908ea99b36e6ab72f13488bbfe622183/src/Oracle.sol#L121-L122

Vulnerability details

Impact

The Oracle's viewPrice() and getPrice() functions retrieve the price of a specific token adjusted for token and feed decimals before applying the collateral factor. While it uses the token's and feed's decimals() function to retrieve their respective decimals, it uses a hardcoded (36) value during normalization.

Given the potential consequences of an invalid result, if the feed and/or token decimals are expected to be fixed, either there is no point in querying the decimals count or there shoud be a guard condition (require / if-revert). The hardcoding solution is only mentioned to point out the need for a guard condition or a proper normalization code.

With the current code, depending on the token/feed pair's decimals count, the normalizedPrice may either result in an invalid scaling by excess or by defect. A corrected normalization is proposed, with a tiny change, in the mitigation section.

Proof of Concept

https://github.com/code-423n4/2022-10-inverse/blob/3e81f0f5908ea99b36e6ab72f13488bbfe622183/src/Oracle.sol#L87-L88

https://github.com/code-423n4/2022-10-inverse/blob/3e81f0f5908ea99b36e6ab72f13488bbfe622183/src/Oracle.sol#L121-L122

Tools Used

n/a

Replace the following two lines of code found here and here

uint8 decimals = 36 - feedDecimals - tokenDecimals;
uint normalizedPrice = price * (10 ** decimals);

with the following code

uint normalizedPrice = tokenDecimals >= feedDecimals
        ? (price * 10**(tokenDecimals - feedDecimals))
        : (price / 10**(feedDecimals - tokenDecimals));

While not recommending a fit-some-cases in exchange of the above's fit-all-cases solution, if still willing to keep the partially hardcoded / partially programmatic decimals normalization code (fit-some-cases), then at least add the following check to the Oracle's viewPrice() and getPrice() functions or to the setFeed() function.

require(tokenDecimals == 18, "Unsupported token")

#0 - c4-judge

2022-11-05T21:13:36Z

0xean marked the issue as duplicate

#1 - c4-judge

2022-11-28T16:06:30Z

0xean marked the issue as partial-50

#2 - c4-judge

2022-11-28T16:06:37Z

0xean marked the issue as not a duplicate

#3 - c4-judge

2022-11-28T16:06:45Z

0xean marked the issue as duplicate of #540

#4 - Simon-Busch

2022-12-05T15:33:30Z

Issue marked as satisfactory as requested by 0xean

#5 - c4-judge

2022-12-07T08:18:20Z

Simon-Busch marked the issue as duplicate of #533

Awards

0.385 USDC - $0.38

Labels

bug
2 (Med Risk)
satisfactory
edited-by-warden
duplicate-584

External Links

Lines of code

https://github.com/code-423n4/2022-10-inverse/blob/3e81f0f5908ea99b36e6ab72f13488bbfe622183/src/Oracle.sol#L82 https://github.com/code-423n4/2022-10-inverse/blob/3e81f0f5908ea99b36e6ab72f13488bbfe622183/src/Oracle.sol#L116

Vulnerability details

Impact

There are a two issues with the Oracle's viewPrice() and getPrice() functions:

  1. Use of deprecated latestAnswer() API which may stop working in the future;
  2. Lack of validation for stale data, which may create conditions for financial loss / attacks.

Proof of Concept

Use of deprecated API without stale data validation

https://github.com/code-423n4/2022-10-inverse/blob/3e81f0f5908ea99b36e6ab72f13488bbfe622183/src/Oracle.sol#L82 https://github.com/code-423n4/2022-10-inverse/blob/3e81f0f5908ea99b36e6ab72f13488bbfe622183/src/Oracle.sol#L116

Deprecated API reference doc

https://docs.chain.link/docs/data-feeds/price-feeds/api-reference/#latestanswer

Real life case of DeFi hack due to Chainlink stale data

https://blog.venus.io/venus-protocol-luna-incident-update-2-c334475d9214

Tools Used

n/a

Use latestRoundData() API and do verify for stale data eventually suspending the service if stale data is found like in cases feed suspension during extreme market volatility (e.g. see Venus Protocol hack during Chainlink LUNA price feed suspension)

diff --git a/src/Oracle.sol b/src/Oracle.sol
index 14338ed..d56d118 100644
--- a/src/Oracle.sol
+++ b/src/Oracle.sol
@@ -79,8 +79,10 @@ contract Oracle {
         if(fixedPrices[token] > 0) return fixedPrices[token];
         if(feeds[token].feed != IChainlinkFeed(address(0))) {
             // get price from feed
-            uint price = feeds[token].feed.latestAnswer();
-            require(price > 0, "Invalid feed price");
+            (, int256 answer, , uint256 updatedAt, ) = feeds[token].feed.latestRoundData();
+            require(block.timestamp <= updatedAt + PRICE_MAX_AGE, "Stale feed detected");
+            require(answer > 0, "Invalid feed price");
+            uint price = uint(answer);
             // normalize price
             uint8 feedDecimals = feeds[token].feed.decimals();
             uint8 tokenDecimals = feeds[token].tokenDecimals;
@@ -113,8 +115,11 @@ contract Oracle {
         if(fixedPrices[token] > 0) return fixedPrices[token];
         if(feeds[token].feed != IChainlinkFeed(address(0))) {
             // get price from feed
-            uint price = feeds[token].feed.latestAnswer();
-            require(price > 0, "Invalid feed price");
+            (, int256 answer, , uint256 updatedAt, ) = feeds[token].feed.latestRoundData();
+            require(block.timestamp <= updatedAt + PRICE_MAX_AGE, "Stale feed detected");
+            require(answer > 0, "Invalid feed price");
+            uint price = uint(answer);
             // normalize price
             uint8 feedDecimals = feeds[token].feed.decimals();
             uint8 tokenDecimals = feeds[token].tokenDecimals;

Refer to Chainlink's StalenessFlaggingValidator.

If deploying to L2, extra caution should be taken for L2 Sequencer uptime as shown in the following Chainlink example.

#0 - neumoxx

2022-10-31T08:51:37Z

Duplicate of #601

#1 - c4-judge

2022-11-05T17:53:57Z

0xean marked the issue as duplicate

#2 - Simon-Busch

2022-12-05T15:25:03Z

Issue marked as satisfactory as requested by 0xean

#3 - c4-judge

2022-12-07T08:14:13Z

Simon-Busch marked the issue as duplicate of #584

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