Lack of Oracle staleness check can cause over-borrowing and unfair liquidations
还没有人认领这个 Issue。
评估
- 难度
- 5/5
- 预计耗时
- 一周以上
- 新手友好度
- 30/100
- Issue 类型
- 缺陷
- 描述清晰度
- 基本清楚
- 活跃度
- 停滞
- 技术栈
- solidity
- 领域
- blockchain, security
调研方向
从 Auditor.assetPrice 和 IPriceFeed 接口开始,然后追踪返回值如何传递到 accountLiquidity、checkBorrow、checkLiquidation 和 calculateSeize。定义 feed 的新鲜度要求和每个 feed 的配置,然后通过有针对性的测试验证过期值不能支持借款或清算决策。
由索引模型根据 Issue 内容生成。
描述
Summary
Auditor.assetPrice() trusts IPriceFeed.latestAnswer() and only checks price > 0. But it does not verify that the oracle value is fresh (no timestamp/round/heartbeat validation).
During a real world Chainlink stalls (sequencer downtime, feed pauses/delays, node issues), latestAnswer() commonly returns the last valid price without reverting, which this protocol will treat as current.
-
This can enable two issues in this contracts:
-
(1) over-borrow using stale-high collateral prices (bad debt / lender loss)
-
(2) liquidations using stale-low collateral prices (steal from users).
Root cause
Auditor.assetPrice():
function assetPrice(IPriceFeed priceFeed) public view returns (uint256) {
if (address(priceFeed) == BASE_FEED) return basePrice;
int256 price = priceFeed.latestAnswer();
if (price <= 0) revert InvalidPrice();
return uint256(price) * baseFactor;
}
- No
updatedAt, noheartbeat, noansweredInRoundchecks(the IPriceFeed interface only exposes latestAnswer()/decimals()).
If you notice this price is used throughout critical logic, e.g. collateral/debt valuation:
vars.price = assetPrice(m.priceFeed);
sumCollateral += vars.balance.mulDivDown(vars.price, baseUnit).mulWadDown(adjustFactor);
sumDebtPlusEffects += vars.borrowBalance.mulDivUp(vars.price, baseUnit).divWadUp(adjustFactor);
- and borrow eligibility:
(uint256 collateral, uint256 debt) = accountLiquidity(borrower, Market(address(0)), 0);
if (collateral < debt) revert InsufficientAccountLiquidity();
- Liquidation math also depends on
assetPrice()(e.g. checkLiquidation, calculateSeize).
Impact
- Over-borrow with stale-high collateral price → protocol/lenders eat bad debt
Condition and likelihood: collateral oracle is stale at an old higher price during a drop (common during L2 sequencer incidents or oracle delays).
Flow:
- Attacker deposits collateral and enters market.
- Calls
Market.borrow(...). Auditor.checkBorrow()→accountLiquidity()uses the stale high price, inflating collateral value → borrow passes.- Attacker exits with borrowed assets.
After: once the oracle updates, the position becomes underwater; liquidation may not fully cover → bad debt.
- Unfair liquidation with stale-low collateral price → steal from users
Condition and likelihood: oracle is stale at an old lower price during a pump.
Flow
- A borrower who is healthy at the real price appears unhealthy at the stale-low price.
- Liquidator calls Market.liquidate(...).
Auditor.checkLiquidation()/Auditor.calculateSeize()use the stale-low collateral price, enabling liquidation and determining seize amounts on wrong inputs.
Impact: borrower loses collateral even though they were healthy at real market prices; liquidator profits.
Recommendation
- Replace
IPriceFeed.latestAnswer()with a Chainlink-style interface exposinglatestRoundData()and enforce freshness:
require(updatedAt >= block.timestamp - MAX_STALENESS)
- Make staleness thresholds per-feed configurable (governance-set) since heartbeats differ across assets/chains.
@cruzdanilo @pmolina @lucaslain
Pls take a look at this, as i have other issues of bugs i would be submitting for this contract.
- 主要语言
- Solidity
- 星标
- 92
- 派生
- 44
- 平均合并
- 8 天 7 小时
- 30 天内合并 PR
- 4
环境准备
这个项目没有提供开发容器、Dockerfile 或贡献指南,环境需要你自己搭建:先看它的 README,通用步骤见我们的新手贡献指南。
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
exactly/protocol 的其他 Issue
-
难度 2/5 1-3 小时 新手友好度 76/100
-
难度 5/5 一周以上 新手友好度 15/100
-
protocol: repay/liquidate with shares可能重新可做 @itofarina 于 274 天前认领,目前没有进行中的 PR。 未关闭question
-
难度 4/5 3-5 天 新手友好度 35/100
-
难度 5/5 一周以上 新手友好度 15/100
相似的 Issue
-
难度 2/5 1-3 小时 新手友好度 84/100
erigontech/erigon#25432 ·
维护者通常 1 天内回复
-
performance
难度 2/5 1-3 小时 新手友好度 75/100
Hamplard-Hub/Hamplard--contracts#706 ·
维护者通常 2 天内回复