Platform: Code4rena
Start Date: 15/03/2024
Pot Size: $60,500 USDC
Total HM: 16
Participants: 43
Period: 21 days
Judge: hansfriese
Total Solo HM: 5
Id: 348
League: ETH
Rank: 26/43
Findings: 2
Award: $91.81
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: Infect3d
Also found by: Evo, LinKenji, XDZIBECX, falconhoof, foxb868, ilchovski, klau5, nonseodion
67.2468 USDC - $67.25
https://github.com/code-423n4/2024-03-dittoeth/blob/91faf46078bb6fe8ce9f55bcb717e5d2d302d22e/contracts/libraries/LibOracle.sol#L22 https://github.com/code-423n4/2024-03-dittoeth/blob/91faf46078bb6fe8ce9f55bcb717e5d2d302d22e/contracts/libraries/LibOracle.sol#L19-L67
If the market experiences significant price volatility within the 15-minute window, the cached price may diverge from the actual market price. This discrepancy can lead to several issues:
Incorrect calculation of collateral ratios:
Mispricing of assets during order matching:
Delayed liquidations of risky positions:
It's from the following: LibOracle.sol#L22
uint256 protocolPrice = getPrice(asset); // ... Oracle price retrieval logic ...
The getPrice
function retrieves the cached price, which may be stale if the cache duration has not expired.
getOraclePrice
is responsible for retrieving the asset price from the oracle. It first attempts to fetch the price from the Chainlink oracle and falls back to a TWAP price from Uniswap if the Chainlink price is invalid or outdated.
function getOraclePrice(address asset) internal view returns (uint256) { AppStorage storage s = appStorage(); AggregatorV3Interface baseOracle = AggregatorV3Interface(s.baseOracle); uint256 protocolPrice = getPrice(asset); <---------@ AggregatorV3Interface oracle = AggregatorV3Interface(s.asset[asset].oracle); <---------@ if (address(oracle) == address(0)) revert Errors.InvalidAsset(); <---------@ try baseOracle.latestRoundData() returns (uint80 baseRoundID, int256 basePrice, uint256, uint256 baseTimeStamp, uint80) { <---------@ // ... Chainlink price retrieval and validation logic ... } catch { if (oracle == baseOracle) { return twapCircuitBreaker(); } else { // ... Fallback to TWAP price ... } } }
retrieves the cached price and the setPriceAndTime
function updates the cached price and timestamp. Is expected to retrieve the most up-to-date and accurate price for an asset from the oracle. The retrieved price should reflect the current market conditions and be used for various calculations and checks within the protocol.
Note:
The 15-minute cache duration, the
getOraclePrice
function may deviate from the expected behavior. If the market price changes significantly within the 15-minute window, the cached price may not accurately represent the current market conditions.
This can lead to incorrect calculations, mispricing of assets, and delayed liquidations, as described in the vulnerability details section.
Let's consider a hypothetical scenario where the DittoETH protocol is used for trading a stablecoin pegged to the US dollar (e.g., USDC) against ETH. The protocol relies on the Chainlink ETH/USD price oracle to determine the current market price of ETH.
Assume the following initial conditions:
Then takes these steps:
Bob observes that the cached ETH/USD price in the DittoETH protocol is stale and significantly higher than the actual market price. The protocol is still using the cached price of $2,000, while the market price has dropped to $1,500.
Bob quickly opens a large short position on the ETH/USD pair, taking advantage of the stale cached price. Since the protocol calculates the collateral ratio based on the cached price, Bob's short position appears to be sufficiently collateralized.
Bob then manipulates the market by placing a large sell order on an external exchange, driving the market price of ETH further down to $1,200.
Alice's short position, which was initially above the liquidation threshold, is now undercollateralized based on the actual market price. However, since the DittoETH protocol is still using the stale cached price of $2,000, Alice's position appears to be adequately collateralized, and no liquidation is triggered.
Bob waits for the cache duration to expire and the protocol to update the cached price to the current market price of $1,200. At this point, Alice's position becomes severely undercollateralized.
Bob quickly buys back the ETH at the lower price, closing his short position at a significant profit. Meanwhile, Alice's position remains open and is at risk of liquidation.
When the protocol finally updates the cached price and detects Alice's undercollateralized position, it triggers a liquidation. However, due to the delayed liquidation, the protocol may struggle to find sufficient liquidity to close Alice's position at the current market price, potentially leading to a cascade of liquidations and further price instability.
Consequences:
function getOraclePrice(address asset) internal view returns (uint256) { uint256 cachedPrice = getPrice(asset); uint256 cacheTimestamp = getPriceTimestamp(asset); if (block.timestamp - cacheTimestamp > 15 minutes) { // Cache duration expired, update the cached price uint256 currentPrice = fetchCurrentPrice(asset); setPrice(asset, currentPrice); setPriceTimestamp(asset, block.timestamp); return currentPrice; } else { // Use the cached price return cachedPrice; } }
If the cache duration has not expired (i.e., less than 15 minutes have passed since the last price update), the function returns the cached price (
cachedPrice
). However, if the market price has changed significantly during this period, the returned price may be stale and not reflect the current market conditions, leading to the issues described in the vulnerability details section.
Manual Review
Consider implementing the mitigation measures discussed earlier, such as reducing the cache duration, implementing price deviation checks, using multiple Oracle price feeds, and regularly updating the Oracle integration to ensure the most accurate and up-to-date prices are used for various calculations and decisions within the protocol.
The price deviation check can be implemented:
function getOraclePrice(address asset) internal view returns (uint256) { // ... Existing code ... + uint256 cachedPrice = getPrice(asset); + uint256 currentPrice = fetchCurrentPrice(asset); // Retrieve the current price from the oracle + if (cachedPrice > 0) { + uint256 deviation = (currentPrice > cachedPrice) ? currentPrice - cachedPrice : cachedPrice - currentPrice; + if (deviation * 100 / cachedPrice > 10) { // Check if deviation exceeds 10% + // Trigger an alert or emergency action // ... } } // ... Existing code ... }
As can be seen, the getOraclePrice
function compares the cached price with the current price fetched from the oracle. If the deviation between the two prices exceeds a threshold (e.g., 10%), an alert or emergency action can be triggered to handle the significant price movement.
Other
#0 - c4-pre-sort
2024-04-06T06:01:39Z
raymondfam marked the issue as sufficient quality report
#1 - c4-pre-sort
2024-04-06T06:01:55Z
raymondfam marked the issue as duplicate of #114
#2 - raymondfam
2024-04-06T06:02:38Z
See #114.
#3 - c4-judge
2024-04-11T16:12:40Z
hansfriese marked the issue as satisfactory
🌟 Selected for report: popeye
Also found by: 0xbrett8571, JcFichtner, LinKenji, Rhaydden, SAQ, Sathish9098, albahaca, clara, emerald7017, fouzantanveer, foxb868, hunter_w3b, kaveyjoe, roguereggiant
24.5635 USDC - $24.56
DittoETH is a decentralized stablecoin protocol that utilizes an order book design to enable supercharged staking yield for users. The protocol aims to create stable assets backed by over-collateralized liquid staked ETH (LST), such as rETH and stETH. By leveraging an order book mechanism, DittoETH allows users to participate as bidders, shorters, or askers, facilitating the minting and trading of stable assets while providing attractive yield opportunities.
The DittoETH protocol utilizes a unique order book design to enable supercharged staking yield for users. The architecture revolves around the interaction of various components, including the Diamond proxy pattern, facets, libraries, and external contracts.
DittoETH Architecture Overview
+---------------------------+ | DittoETH Protocol | +---------------------------+ | | | +-----------------+ | | | Order Book | | | +-----------------+ | | | - Bids | | | | - Shorts | | | | - Asks | | | +-----------------+ | | | | +-----------------+ | | | Collateral | | | | Management | | | +-----------------+ | | | - LST Collateral| | | | - Collateral | | | | Ratios | | | +-----------------+ | | | | +-----------------+ | | | Liquidations | | | +-----------------+ | | | - Undercollate- | | | | ralized Shorts| | | | - Liquidation | | | | Mechanism | | | +-----------------+ | | | | +-----------------+ | | | Yield | | | | Distribution | | | +-----------------+ | | | - LST Rewards | | | | - Bidder's | | | | Collateral | | | +-----------------+ | | | | +-----------------+ | | | Governance | | | +-----------------+ | | | - Token Holders | | | | - Proposals | | | | - Voting | | | +-----------------+ | | | +---------------------------+ | | | | +------+------------+-------+ | | | | | +---+----+ +----+---+ | | | Bidders| |Shorters| | | +--------+ +--------+ | | | | +--------+ +--------+ | | | Askers | |Liquidat| | | | | | ors | | | +--------+ +--------+ | | | +---------------------------+
Diamond proxy pattern introduces complexity in terms of code organization and upgradability. Ensure thorough testing and auditing of the facet interactions and storage layout to mitigate potential risks.
The interaction between facets and shared storage can lead to unintended consequences if not properly managed. Implement strict access controls and validation checks to prevent unauthorized access or manipulation of shared storage.
The upgradability of facets through the Diamond proxy requires careful consideration. Establish a robust governance process and testing framework to ensure the integrity and security of upgrades.
DittoETH demonstrates a modular and organized structure, leveraging the Diamond proxy pattern for upgradability and separation of concerns. The use of libraries and constants helps improve code reusability and readability. However, there are areas that require attention to enhance the overall codebase quality.
Error Handling and Validation:
Observation: The codebase extensively uses the revert
statement for error handling, which is a good practice. However, some functions lack proper input validation, which could lead to unexpected behavior or vulnerabilities.
Recommendation: Implement comprehensive input validation checks for all external and public functions to ensure the correctness and integrity of the input data.
Code Documentation and Comments:
Gas Optimization:
struct Order { uint88 ercAmount; uint80 price; uint16 prevId; uint16 id; uint16 nextId; O orderType; uint32 creationTime; address addr; O prevOrderType; uint16 shortOrderCR; uint8 shortRecordId; uint64 filler; }
Admin Roles and Privileges:
Observation: The DittoETH protocol includes admin roles with significant privileges, such as the ability to create markets, adjust protocol parameters, and manage bridges.
Recommendation: Implement a multi-sig or decentralized governance mechanism to distribute control and reduce the risk of a single point of failure or admin abuse.
Bridge Management:
Observation: The protocol allows the admin to create and delete bridges, which could potentially impact user funds if not managed properly.
Recommendation: Establish strict guidelines and governance processes for bridge management to ensure the security and integrity of user funds. Consider implementing time-locks or multi-sig controls for critical bridge operations.
Parameter Adjustments:
Observation: The admin has the ability to modify various protocol parameters, such as fees, liquidation thresholds, and collateral ratios, which could potentially be abused to gain an unfair advantage.
Recommendation: Implement robust governance mechanisms and checks and balances to prevent unilateral parameter changes. Consider using time-locks, multi-sig approvals, or community voting for significant parameter adjustments.
Mechanism Review:
Order Matching Logic:
bidMatchAlgo
function in the BidOrdersFacet
contract handles the matching of bids with asks and shorts. It involves intricate logic and loops, which could be prone to errors or manipulation.Liquidation Mechanism:
liquidate
function in the PrimaryLiquidationFacet
contract allows liquidators to liquidate undercollateralized short positions. It depends on the accuracy of the oracle price and the correctness of the liquidation logic.Redemption Mechanism:
proposeRedemption
function in the RedemptionFacet
contract enables users to propose a redemption order based on the collateral ratios of short positions. It relies on user input and is subject to potential manipulation.Oracle Dependency:
Liquidity and Market Dynamics:
Governance and Upgradability:
Stable Asset Creation: DittoETH enables the creation of stable assets, such as dUSD, which are backed by LST collateral. Users can mint stable assets by placing bids on the order book, while shorters provide the necessary collateral and take on a short position.
Order Book Mechanism: The protocol employs an order book design that matches bids and shorts to determine the price and quantity of stable assets minted. Bidders bring ETH to purchase stable assets, while shorters bring ETH as collateral and take a leveraged short position against the stable asset.
Collateral Management: DittoETH ensures that short positions are always over-collateralized to maintain the stability of the minted assets. Shorters must provide sufficient collateral to cover their short positions, and the protocol enforces liquidation mechanisms to manage undercollateralized positions.
Yield Generation: Shorters earn a supercharged yield on their collateral, as they receive the staking rewards generated by the LST collateral in addition to the bidder's collateral. This mechanism incentivizes shorters to participate and provides an attractive yield opportunity.
Liquidations and Risk Management: DittoETH incorporates liquidation mechanisms to handle undercollateralized short positions. When a short position falls below the required collateral ratio, liquidators can step in to liquidate the position and maintain the stability of the system.
Minting Stable Assets: Users can mint stable assets, such as dUSD, by placing bids on the order book. Bids are matched with short positions to determine the price and quantity of stable assets minted.
Shorting: Shorters provide collateral in the form of LST (e.g., rETH or stETH) and take a short position against the stable asset. They earn a yield on their collateral, which includes the staking rewards and the bidder's collateral.
Collateral Management: The protocol manages the collateral provided by shorters, ensuring that short positions remain over-collateralized. It tracks the collateral ratios and triggers liquidations when necessary.
Order Matching: The order book mechanism matches bids and shorts based on price and quantity. It determines the price at which stable assets are minted and facilitates the exchange between bidders and shorters.
Liquidations: When a short position falls below the required collateral ratio, liquidators can initiate the liquidation process. They buy back the stable assets and receive a liquidation fee, while the remaining collateral is used to cover any outstanding debt.
Governance: DittoETH incorporates a governance mechanism that allows token holders to participate in decision-making processes, such as adjusting protocol parameters, managing collateral types, and upgrading the system.
Bidders: Participants who bring ETH to the protocol to purchase stable assets. They place bids on the order book, specifying the price and quantity they are willing to buy.
Shorters: Participants who provide LST collateral and take a short position against the stable asset. They earn a yield on their collateral and are responsible for maintaining the required collateral ratio.
Askers: Participants who sell their stable assets on the order book, specifying the price and quantity they are willing to sell.
Liquidators: Participants who monitor the system for undercollateralized short positions and initiate liquidations when necessary. They buy back the stable assets and receive a liquidation fee.
Governance Token Holders: Participants who hold governance tokens and have the right to participate in the decision-making processes of the protocol.
User Interaction: Users interact with the DittoETH protocol through a web interface or API, allowing them to place bids, create short positions, and manage their assets.
Smart Contracts: The core functionality of DittoETH is implemented through a set of smart contracts deployed on the Ethereum blockchain. These contracts handle the minting and burning of stable assets, order matching, collateral management, and liquidations.
Order Book: The order book is a central component of the DittoETH protocol. It maintains a list of bids and shorts, sorted by price. When a new bid or short is placed, the order book matches it with existing orders based on price and quantity.
Collateral Management: The protocol tracks the collateral provided by shorters and ensures that short positions remain over-collateralized. It continuously monitors the collateral ratios and triggers liquidations when necessary.
Liquidations: When a short position falls below the required collateral ratio, the protocol initiates the liquidation process. Liquidators step in to buy back the stable assets and receive a liquidation fee, while the remaining collateral is used to cover any outstanding debt.
Yield Distribution: The protocol distributes the yield earned by shorters, which includes the staking rewards from the LST collateral and the bidder's collateral. This yield is automatically calculated and distributed to shorters based on their collateral contribution.
Governance: DittoETH incorporates a governance mechanism that allows token holders to participate in decision-making processes. Governance proposals can be submitted, discussed, and voted on by token holders to make changes to the protocol's parameters or upgrade the system.
Vulnerability: Redemption Mechanism - Incorrect Redemption Order Description:
Potential Impact:
Recommendation:
Vulnerability: Orderbook Matching Logic - Incorrect Matching of Short Orders Description:
Potential Impact:
Recommendation:
Vulnerability: Oracle Price Caching - Stale Prices and Manipulation Description:
Potential Impact:
Recommendation:
Vulnerability: Dust Amounts - Increased Gas Costs and Orderbook Bloat Description:
Potential Impact:
Recommendation:
Vulnerability: Liquidation and Collateral Ratio Manipulation Description:
minShortErc
to ensure that liquidators have sufficient incentive to liquidate risky debt positions.minShortErc
or the liquidation process, it could lead to potential manipulation of collateral ratios.Potential Impact:
Recommendation:
minShortErc
and the liquidation process to ensure they are robust and free from loopholes.Vulnerability: Incorrect Liquidation or Exiting of Short Positions Description:
Potential Impact:
Recommendation:
Additional Observations and Suggestions:
By addressing these vulnerabilities and implementing the recommended mitigation measures, the DittoETH protocol can enhance its security posture, protect user funds, and maintain the integrity of its economic model.
Order Book Manipulation:
Collateral Management:
Liquidation Mechanism:
Governance and Upgradability:
External Dependencies:
I believe by addressing these potential weaknesses and entry points, the DittoETH protocol can enhance its security posture and reduce the risk of exploits or attacks.
Let's dive deeper into the potential weaknesses and weak points of the DittoETH protocol.
1. Dependency on External Oracles: The DittoETH protocol relies heavily on external price oracles for accurate pricing information. If the oracle is compromised, manipulated, or fails to provide timely updates, it can lead to mispricing of assets and potential exploits.
Recommendation:
The DittoETH protocol presents a novel approach to decentralized stablecoins with its order book design and supercharged staking yield. While the code demonstrates a modular and organized structure, there are areas that require attention to enhance security which i highlighted and described some of them, mitigate centralization risks, and ensure the robustness of the protocol.
The identified risks and vulnerabilities, such as the complexity of the Diamond proxy pattern, potential for admin abuse, and dependency on accurate price oracles, should be carefully addressed through a combination of technical improvements, governance mechanisms, and thorough testing and auditing.
By implementing the recommended mitigation measures, enhancing code quality, and establishing robust governance processes, the DittoETH protocol can strengthen its security posture, protect user funds, and inspire confidence in its users and the wider DeFi ecosystem.
10 hours
#0 - c4-pre-sort
2024-04-07T20:24:03Z
raymondfam marked the issue as sufficient quality report
#1 - c4-judge
2024-04-17T07:06:03Z
hansfriese marked the issue as grade-b