fix(morpho): require 8-decimal upstream oracle (audit #187)#224
Open
hardyjosh wants to merge 2 commits into
Open
fix(morpho): require 8-decimal upstream oracle (audit #187)#224hardyjosh wants to merge 2 commits into
hardyjosh wants to merge 2 commits into
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This was referenced May 11, 2026
Collaborator
Author
This was referenced May 11, 2026
Closed
Closed
50d26bd to
8d871ae
Compare
e479257 to
dc9ec25
Compare
a311916 to
f505724
Compare
7e068f3 to
44edffa
Compare
f505724 to
25d31e3
Compare
44edffa to
9bd9d66
Compare
9bd9d66 to
9b397c2
Compare
427065b to
a153778
Compare
9b397c2 to
d2838f5
Compare
a153778 to
336605a
Compare
d2838f5 to
f3e41d2
Compare
…md sync Bundles the documentation-only changes for the audit MEDIUMs whose right answer was "tell the truth in the spec/docs" rather than "change the code". - #27 SPEC.md: add MultiPythOracleAdapter, BasePythOracleAdapter, MultiPythOracleAdapterBeaconSetDeployer, MultiOracleUnifiedDeployer to §3, §6, §9, §10, §11; add IAggregatorV2V3 and LibCorporateActionsPause to §11. Repo tree now matches src/. - #28 CLAUDE.md: architecture summary names BasePythOracleAdapter, MultiPythOracleAdapter, the auto-pause mechanism, and the OraclePausedManual / OraclePausedCorporateAction selectors; repo tree reflects src/abstract/, src/interface/IAggregatorV2V3.sol, src/lib/LibCorporateActionsPause.sol, and the Multi-* deployers; dependencies list adds st0x.deploy. - #29 SPEC.md: single-feed PythOracleAdapter is fully immutable post-init (no priceId / maxAge setters); MultiPythOracleAdapter has admin-controlled setFeeds and setMaxAge. §3 diagram and §13 governance updated to match implementation. - #164 SPEC.md §9: newOracleRegistry() correctly described as no-args with msg.sender becoming admin; rationale added (eliminates an attacker-controlled admin slot in a permissionless factory). - #199 LibCorporateActionsPause.sol: @dev note on `inPauseWindow` documenting that the upper-bound predicates are enforced by the upstream CompletionFilter, not locally; future vault regressions surface here as fail-open; mitigation via upstream conformance test tracked at #216. - #209 OracleUnifiedDeployer.sol and MultiOracleUnifiedDeployer.sol: contract-level @dev note documenting that sub-deployer addresses (LibProdDeploy.*) are inlined at compile time; redeploying any sub-deployer requires redeploying this contract too. - #210 AGENTS.md Deployment: pipeline-drift-risk callout describing the manual log-parse → operator-PR pipeline and the typo / wrong-slot / untimely-PR risks; references #210 and the related #220 networks.json duplication. - #212 IAggregatorV2V3.sol: SYNC NOTE comment pointing to smartcontractkit/chainlink:contracts/src/v0.8/shared/interfaces/AggregatorV2V3Interface.sol, last synced 2026-05-11, and noting the missing drift-detection test tracked at #212. - #220 subgraph/README.md (new): documents the by-hand duplication between subgraph/networks.json and src/lib/LibProdDeploy.sol, and tracks the gen-pipeline overhaul at #220. No executable code changed. nix CI green: - rainix-sol-test, rainix-sol-static, rainix-sol-legal all pass. - LibCorporateActionsPauseTest still 17/17 (NatSpec-only edit). Closes #27, #28, #29, #164, #199, #209, #210, #212, #220. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
MorphoProtocolAdapter.price() unconditionally scales `latestAnswer() * 1e28`, which is correct iff the upstream oracle reports 8 decimals. `OracleRegistry.setOracle()` doesn't constrain decimals — a registry swap to an 18-decimal feed (e.g. a future Chainlink integration) would silently mis-price Morpho collateral by 10^10×. There is no observable revert; Morpho would just see a wildly wrong number. Adds: - `EXPECTED_ORACLE_DECIMALS` constant (= 8) derived from the `36 - 8` scaling exponent. - `UnexpectedOracleDecimals(uint8 actual, uint8 expected)` error. - A `decimals()` check at the top of `price()`, BEFORE `latestAnswer()` is read, so a misconfigured oracle fails loudly before the wrong number ever enters the computation. Tests: - testPriceRevertsOnNonEightDecimals — fuzz over every uint8 != 8 and assert the new revert fires with the right payload. - testPriceDecimalsCheckRunsBeforeAnswer — mocks `latestAnswer` to revert; confirms the decimals check fires first. - All four existing positive tests updated to mock `oracle.decimals()` to 8 (default-zero would now hit the new revert). - AutoPausePropagation tests continue to pass — they use the real PythOracleAdapter which hardcodes `decimals = 8`. Closes #187. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
f3e41d2 to
dd82097
Compare
6d85151 to
2134c50
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

MorphoProtocolAdapter.price() unconditionally scales
latestAnswer() * 1e28, which is correct iff the upstream oracle reports 8 decimals.OracleRegistry.setOracle()doesn't constrain decimals — a registryswap to an 18-decimal feed (e.g. a future Chainlink integration) would
silently mis-price Morpho collateral by 10^10×. There is no observable
revert; Morpho would just see a wildly wrong number.
Adds:
EXPECTED_ORACLE_DECIMALSconstant (= 8) derived from the36 - 8scaling exponent.
UnexpectedOracleDecimals(uint8 actual, uint8 expected)error.decimals()check at the top ofprice(), BEFORElatestAnswer()is read, so a misconfigured oracle fails loudly before the wrong
number ever enters the computation.
Tests:
assert the new revert fires with the right payload.
latestAnswertorevert; confirms the decimals check fires first.
oracle.decimals()to 8 (default-zero would now hit the new revert).
PythOracleAdapter which hardcodes
decimals = 8.Closes #187.
Co-Authored-By: Claude Opus 4.7 noreply@anthropic.com