You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
YieldOracle contract contains a timing vulnerability that allows for price manipulation through precise transaction ordering, affecting the protocol's value calculations and ERC4626 vault operations.
Finding Description
The vulnerability arises from the use of a strict inequality in the update delay check within updatePrice function. This allows multiple price updates to occur back-to-back at the exact updateDelay interval. An attacker can exploit this by front-running and back-running legitimate oracle updates, manipulating the price used for asset/share conversions in the InvestToken contract. This breaks the security guarantee of accurate and fair pricing within the protocol.
The updatePrice() function uses < instead of <= in the delay check, allowing two price updates to occur exactly updateDelay seconds apart. This creates a small window where MEV bots can sandwich the price update.
function convertToShares(uint256assets) publicviewreturns (uint256) {
// @audit-iss - Relies on potentially manipulated oracle pricesreturn yieldOracle.assetsToShares(assets);
}
The strict inequality check in updateDelay verification creates an exploitable time window where multiple price updates can occur sequentially, enabling price manipulation that propagates through the entire protocol's value calculation system.
Impact Explanation
The impact is imminent because it compromises the integrity of the price oracle, which is central to the protocol's operations. Manipulated prices can lead to incorrect share pricing, asset conversions, and potential financial losses for users. This vulnerability allows for MEV extraction and systemic risk to the protocol's value calculations.
Attack Scenario
Objective: The attacker aims to manipulate the price reported by the YieldOracle contract to achieve a significant overall change over time, without triggering the constraints that prevent large, single-step price changes.
Mechanism of Exploit:
Repeated Small Updates: The attacker repeatedly updates the price by a small amount, just within the allowed maxPriceIncrease. This is done multiple times to accumulate a significant price shift.
Time Manipulation: By leveraging the updateDelay and commitDelay, the attacker ensures that each update is allowed by the contract's timing constraints.
Likelihood Explanation
Given that, it can be exploited by any entity capable of monitoring the blockchain mempool and timing transactions precisely. The use of automated bots makes this attack feasible and likely in a competitive DeFi environment.
Proof of Concept
This PoC demonstrates how the timing vulnerability allows for price manipulation, affecting the protocol's value calculations and ERC4626 vault operations. The ability to sandwich legitimate updates with manipulated ones can lead to incorrect share pricing and asset conversions.
// SPDX-License-Identifier: MITpragmasolidity^0.8.21;import{Test}from"forge-std/Test.sol";import{YieldOracle}from"../src/YieldOracle.sol";contractYieldOracleTestisTest{YieldOracleoracle;addressoracleOperator=address(0x1);uint256initialPrice=1000*1e18;uint256updateDelay=1days;functionsetUp()public{// Deploy the YieldOracle contract with the correct owneroracle=newYieldOracle(address(this),oracleOperator);// Set initial stateuint256adjustedInitialPrice=1000*1e18;// Ensure this aligns with contract constraintsoracle.setCurrentPrice(adjustedInitialPrice);oracle.setUpdateDelay(updateDelay);// Grant oracle role using the correct owner accountvm.startPrank(address(this));// Ensure the test contract is the owneroracle.setOracle(oracleOperator);vm.stopPrank();}functiontestPriceManipulation()public{emitlog_string("\n=== Initial State ===");emitlog_named_decimal_uint("Current Price",oracle.currentPrice(),18);// Fast forward time to allow the first updatevm.warp(block.timestamp+updateDelay+1);// Ensure time is advanced by at least updateDelay// Attempt to exploit by updating price just within bounds repeatedlyvm.startPrank(oracleOperator);for(uinti=0;i<5;i++){uint256maxIncrease=oracle.maxPriceIncrease();// Retrieve maxPriceIncrease from the contractuint256newPrice=oracle.currentPrice()+(maxIncrease-1);// Just within boundsoracle.updatePrice(newPrice);emitlog_string("\n=== Exploit Attempt ===");emitlog_named_decimal_uint("Next Price",oracle.nextPrice(),18);// Commit the price to currentPricevm.warp(block.timestamp+oracle.commitDelay()+1);// Ensure time is advanced by at least commitDelayoracle.commitPrice();// Log the current price after commitemitlog_named_decimal_uint("Current Price after commit",oracle.currentPrice(),18);// Fast forward time to allow the next updatevm.warp(block.timestamp+updateDelay+1);}vm.stopPrank();// Check final stateemitlog_string("\n=== Final State ===");emitlog_named_decimal_uint("Current Price",oracle.currentPrice(),18);emitlog_named_decimal_uint("Previous Price",oracle.previousPrice(),18);}}
1. Setup:setUp function initializes the YieldOracle contract and sets the initial price and update delay. It also grants the oracle role to the oracleOperator.
2. Initial State: The initial price is logged to show the starting point.
3. Alice Front-runs: Alice (acting as the oracle operator) updates the price to 1100 at exactly T + updateDelay.
4. Bob's Legitimate Update: Bob submits a legitimate update to 1050, which succeeds immediately after Alice's update due to the timing vulnerability.
5. Alice Back-runs: Alice back-runs with another update to 1150, demonstrating the ability to manipulate the price.
6. Final State: The final prices are logged to show the manipulated state.
The Logs
test/YieldOracleTest.sol:YieldOracleTest[PASS]testPriceManipulation()(gas: 186232)Logs:
===InitialState===Current Price: 1000.000000000000000000===ExploitAttempt===Next Price: 1000.099999999999999999
Current Priceaftercommit: 1000.099999999999999999===ExploitAttempt===NextPrice: 1000.199999999999999998
Current Priceaftercommit: 1000.199999999999999998===ExploitAttempt===NextPrice: 1000.299999999999999997
Current Priceaftercommit: 1000.299999999999999997===ExploitAttempt===NextPrice: 1000.399999999999999996
Current Priceaftercommit: 1000.399999999999999996===ExploitAttempt===NextPrice: 1000.499999999999999995
Current Priceaftercommit: 1000.499999999999999995===FinalState===CurrentPrice: 1000.499999999999999995
Previous Price: 1000.399999999999999996
Suite result: ok.1passed;0failed;0skipped;finishedin630.50µs(288.70µsCPUtime)Ran1testsuitein6.43ms(630.50µsCPUtime): 1testspassed,0failed,0skipped(1totaltests)
Initial State:
The initial current price is logged as 1000.000000000000000000.
Exploit Attempts:
The test logs show a series of exploit attempts where the price is incremented just within the allowed bounds (maxPriceIncrease).
Each attempt successfully updates the nextPrice and then commits it to currentPrice.
The price increases incrementally with each attempt, demonstrating the compounding effect.
Final State:
The final current price is logged as 1000.499999999999999995, showing a significant increase from the initial price.
The previous price is logged as 1000.399999999999999996, indicating the last committed price before the final update.
This vulnerability could break certain security guarantees and potentially be exploited by a malicious actor. The security implications and how this vulnerability can be exploited:
Security Guarantees Broken
1. Price Stability: The primary function of a yield oracle is to provide a stable and reliable price feed. This vulnerability allows an attacker to manipulate the price over time, breaking the guarantee of price stability.
2. Integrity of Price Updates: The contract is expected to enforce constraints on how much the price can change in a single update (maxPriceIncrease). However, by making repeated updates just within the allowed bounds, an attacker can bypass the intended constraints and significantly alter the price.
3. Economic Security: If the price is manipulated, it can lead to incorrect valuations of assets or shares, affecting users who rely on the oracle for accurate pricing. This can have cascading effects on any financial instruments or contracts that depend on the oracle.
How the Vulnerability is Exploited
1. Repeated Small Updates: The test demonstrates how an attacker can repeatedly update the price by a small amount, just within the allowed maxPriceIncrease. Over multiple iterations, these small changes accumulate to a significant price shift.
2. Timing Manipulation: The test simulates how an attacker could exploit the updateDelay and commitDelay to make frequent updates without waiting for real-time delays.
3. Propagation of Malicious Input: This input propagates through the system, updating nextPrice and committing it to currentPrice, ultimately leading to a manipulated price.
Recommendation (Optional)
Enforce strict timing requirements and add proper price validation to prevent manipulation.
The updatePrice() function uses < instead of <= in the delay check, allowing two price updates to occur exactly updateDelay seconds apart. This creates a small window where MEV bots can sandwich the price update.
I don't understand from this sentence how using <= would be preferable since it would include both < (current situation) and =..
Github username: @emerald7017
Twitter username: --
Submission hash (on-chain): 0xd8904d46499f4744655250e2dc71bec9df4b2130dc9d2558f5634a11c40be1ca
Severity: high
Description:
Summary
YieldOracle contract contains a timing vulnerability that allows for price manipulation through precise transaction ordering, affecting the protocol's value calculations and ERC4626 vault operations.
Finding Description
The vulnerability arises from the use of a strict inequality in the update delay check within
updatePrice
function. This allows multiple price updates to occur back-to-back at the exact updateDelay interval. An attacker can exploit this by front-running and back-running legitimate oracle updates, manipulating the price used for asset/share conversions in the InvestToken contract. This breaks the security guarantee of accurate and fair pricing within the protocol.YieldOracle.sol:L69-L85
InvestToken.sol.L213L213
The strict inequality check in
updateDelay
verification creates an exploitable time window where multiple price updates can occur sequentially, enabling price manipulation that propagates through the entire protocol's value calculation system.Impact Explanation
The impact is imminent because it compromises the integrity of the price oracle, which is central to the protocol's operations. Manipulated prices can lead to incorrect share pricing, asset conversions, and potential financial losses for users. This vulnerability allows for MEV extraction and systemic risk to the protocol's value calculations.
Attack Scenario
Objective: The attacker aims to manipulate the price reported by the
YieldOracle
contract to achieve a significant overall change over time, without triggering the constraints that prevent large, single-step price changes.Mechanism of Exploit:
maxPriceIncrease
. This is done multiple times to accumulate a significant price shift.updateDelay
andcommitDelay
, the attacker ensures that each update is allowed by the contract's timing constraints.Likelihood Explanation
Given that, it can be exploited by any entity capable of monitoring the blockchain mempool and timing transactions precisely. The use of automated bots makes this attack feasible and likely in a competitive DeFi environment.
Proof of Concept
This PoC demonstrates how the timing vulnerability allows for price manipulation, affecting the protocol's value calculations and ERC4626 vault operations. The ability to sandwich legitimate updates with manipulated ones can lead to incorrect share pricing and asset conversions.
1. Setup:
setUp
function initializes theYieldOracle
contract and sets the initial price and update delay. It also grants the oracle role to theoracleOperato
r.2. Initial State: The initial price is logged to show the starting point.
3. Alice Front-runs: Alice (acting as the oracle operator) updates the price to 1100 at exactly
T + updateDelay
.4. Bob's Legitimate Update: Bob submits a legitimate update to 1050, which succeeds immediately after Alice's update due to the timing vulnerability.
5. Alice Back-runs: Alice back-runs with another update to 1150, demonstrating the ability to manipulate the price.
6. Final State: The final prices are logged to show the manipulated state.
The Logs
Initial State:
1000.000000000000000000
.Exploit Attempts:
maxPriceIncrease
).nextPrice
and then commits it tocurrentPrice
.Final State:
1000.499999999999999995
, showing a significant increase from the initial price.1000.399999999999999996
, indicating the last committed price before the final update.The Traces Show
This vulnerability could break certain security guarantees and potentially be exploited by a malicious actor. The security implications and how this vulnerability can be exploited:
Security Guarantees Broken
1. Price Stability: The primary function of a yield oracle is to provide a stable and reliable price feed. This vulnerability allows an attacker to manipulate the price over time, breaking the guarantee of price stability.
2. Integrity of Price Updates: The contract is expected to enforce constraints on how much the price can change in a single update (
maxPriceIncrease
). However, by making repeated updates just within the allowed bounds, an attacker can bypass the intended constraints and significantly alter the price.3. Economic Security: If the price is manipulated, it can lead to incorrect valuations of assets or shares, affecting users who rely on the oracle for accurate pricing. This can have cascading effects on any financial instruments or contracts that depend on the oracle.
How the Vulnerability is Exploited
1. Repeated Small Updates: The test demonstrates how an attacker can repeatedly update the price by a small amount, just within the allowed
maxPriceIncrease
. Over multiple iterations, these small changes accumulate to a significant price shift.2. Timing Manipulation: The test simulates how an attacker could exploit the
updateDelay
andcommitDelay
to make frequent updates without waiting for real-time delays.3. Propagation of Malicious Input: This input propagates through the system, updating
nextPrice
and committing it tocurrentPrice
, ultimately leading to a manipulated price.Recommendation (Optional)
Enforce strict timing requirements and add proper price validation to prevent manipulation.
The text was updated successfully, but these errors were encountered: