Skip to content

Make oracle and treasury configurable through setter functions .#20

Open
Sourav-IIITBPL wants to merge 2 commits into
StabilityNexus:mainfrom
Sourav-IIITBPL:feature/configurable-oracle
Open

Make oracle and treasury configurable through setter functions .#20
Sourav-IIITBPL wants to merge 2 commits into
StabilityNexus:mainfrom
Sourav-IIITBPL:feature/configurable-oracle

Conversation

@Sourav-IIITBPL

@Sourav-IIITBPL Sourav-IIITBPL commented Mar 31, 2026

Copy link
Copy Markdown

Summary

Currently, PYTH_ORACLE, PRICE_ID, and TREASURY in StableCoin.sol are immutable. This prevents:

  • oracle migration in case of failure
  • treasury upgrade for governance evolution

Changes

  • Removed immutability
  • Added events and controlled setters (restricted to treasury)

This prepares the system for:

  • governance upgradability
  • oracle replacement in case of failure
  • safer long-term protocol maintenance

Summary by CodeRabbit

  • New Features

    • Oracle and treasury addresses are now mutable and can be updated via admin functions.
    • Added setOracle() and setTreasury() functions for configuration updates.
    • Added OracleUpdated and TreasuryUpdated events to track administrative changes.
  • Chores

    • Type normalization and formatting adjustments across contracts.

@coderabbitai

coderabbitai Bot commented Mar 31, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

The changes make oracle and treasury state mutable with setter functions and emit events in StableCoin, normalize uint to uint256 types in the IPyth interface for consistency, reformat event and function declarations across multiple files, and remove minor whitespace.

Changes

Cohort / File(s) Summary
Core State Mutability
src/StableCoin.sol
Changed PYTH_ORACLE, PRICE_ID, and TREASURY from immutable to mutable with public visibility. Added external setter functions setOracle() and setTreasury() guarded by onlyTreasury modifier, with non-zero validation and corresponding OracleUpdated and TreasuryUpdated events.
Interface Type Normalization
src/interfaces/IPyth.sol
Normalized function parameter and return types from uint to uint256 across getValidTimePeriod(), getPriceNoOlderThan(), and getUpdateFee() function signatures for type consistency.
Code Formatting & Whitespace
script/Deploy.s.sol, src/StableCoinFactory.sol, src/tokens/Tokeon.sol
Removed empty lines and reformatted multi-line declarations into single-line format for ReactorDeployedWithOracle event emission and Tokeon constructor. No functional changes.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 Immutable chains now break free with a bound,
Oracles mutable—what a wonderful sound!
With setters and events, we dance through the code,
While uint256 unifies the validation road,
Our StableCoin hops forward with grace and with might!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately captures the main objective: making oracle and treasury configurable through setter functions, which aligns with the primary changes in src/StableCoin.sol.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/StableCoin.sol (2)

82-83: Consider indexing address parameters for better event filtering.

Adding indexed to the address parameters would enable efficient off-chain filtering by oracle or treasury address, which is useful for governance monitoring tools.

♻️ Suggested improvement
-    event OracleUpdated(address oldOracle, address newOracle, bytes32 oldPriceId, bytes32 newPriceId);
-    event TreasuryUpdated(address oldTreasury, address newTreasury);
+    event OracleUpdated(address indexed oldOracle, address indexed newOracle, bytes32 oldPriceId, bytes32 newPriceId);
+    event TreasuryUpdated(address indexed oldTreasury, address indexed newTreasury);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/StableCoin.sol` around lines 82 - 83, Update the OracleUpdated and
TreasuryUpdated event declarations to make the address parameters indexed so
off-chain tools can filter by oracle/treasury; specifically modify the
OracleUpdated event (OracleUpdated) to mark oldOracle and newOracle as indexed
and modify TreasuryUpdated (TreasuryUpdated) to mark oldTreasury and newTreasury
as indexed, then run a quick compile to ensure the ABI changes are valid.

166-173: Implementation is correct; consider operational safeguards.

The function logic is sound with proper validation and access control. However, note that treasury transfers are immediate with no timelock or multi-sig requirement. For production deployments, consider implementing a timelock pattern or ensuring the treasury address is a multi-sig/governance contract to prevent single-point-of-failure scenarios.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/StableCoin.sol` around lines 166 - 173, setTreasury currently allows
immediate swaps of TREASURY (function setTreasury) which is correct but risky
for production; add operational safeguards by requiring a timelock or
multi-sig/governance-controlled address for TREASURY: either integrate a
timelock mechanism (e.g., queueTreasuryChange / executeTreasuryChange flow)
around setTreasury or add a runtime check that newTreasury is a known
multisig/governance contract (e.g., verify support for a specific interface or
require isTrustedGovernance(newTreasury)); emit TreasuryUpdated only when the
queued change is executed (or after the verification), and keep existing access
control (onlyTreasury) in place.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/StableCoin.sol`:
- Around line 154-164: The setOracle function validates newOracle but not the
price identifier; add a check in setOracle to require(newPriceId != bytes32(0),
"invalid price id") (or similar) before assigning PRICE_ID to prevent setting
PRICE_ID to zero which would break getBasePriceInPeggedAsset(), fission(), and
transmute functions; keep the rest of the function (capture oldPriceId, assign
PRICE_ID, emit OracleUpdated) unchanged so the OracleUpdated(oldPriceId,
newPriceId) still reflects the validated value.

---

Nitpick comments:
In `@src/StableCoin.sol`:
- Around line 82-83: Update the OracleUpdated and TreasuryUpdated event
declarations to make the address parameters indexed so off-chain tools can
filter by oracle/treasury; specifically modify the OracleUpdated event
(OracleUpdated) to mark oldOracle and newOracle as indexed and modify
TreasuryUpdated (TreasuryUpdated) to mark oldTreasury and newTreasury as
indexed, then run a quick compile to ensure the ABI changes are valid.
- Around line 166-173: setTreasury currently allows immediate swaps of TREASURY
(function setTreasury) which is correct but risky for production; add
operational safeguards by requiring a timelock or
multi-sig/governance-controlled address for TREASURY: either integrate a
timelock mechanism (e.g., queueTreasuryChange / executeTreasuryChange flow)
around setTreasury or add a runtime check that newTreasury is a known
multisig/governance contract (e.g., verify support for a specific interface or
require isTrustedGovernance(newTreasury)); emit TreasuryUpdated only when the
queued change is executed (or after the verification), and keep existing access
control (onlyTreasury) in place.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9abf6281-3eb1-4594-aa95-557c746bf871

📥 Commits

Reviewing files that changed from the base of the PR and between 3b68843 and f5e6ccb.

📒 Files selected for processing (5)
  • script/Deploy.s.sol
  • src/StableCoin.sol
  • src/StableCoinFactory.sol
  • src/interfaces/IPyth.sol
  • src/tokens/Tokeon.sol
💤 Files with no reviewable changes (1)
  • script/Deploy.s.sol

Comment thread src/StableCoin.sol
Comment on lines +154 to +164
function setOracle(address newOracle, bytes32 newPriceId) external onlyTreasury {
require(newOracle != address(0), "invalid oracle");

address oldOracle = address(PYTH_ORACLE);
bytes32 oldPriceId = PRICE_ID;

PYTH_ORACLE = IPyth(newOracle);
PRICE_ID = newPriceId;

emit OracleUpdated(oldOracle, newOracle, oldPriceId, newPriceId);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Missing validation for newPriceId.

The function validates newOracle but not newPriceId. Setting PRICE_ID to bytes32(0) would cause oracle price lookups to fail or return invalid data in functions like getBasePriceInPeggedAsset(), fission(), and the transmute functions.

🛡️ Proposed fix to add validation
 function setOracle(address newOracle, bytes32 newPriceId) external onlyTreasury {
     require(newOracle != address(0), "invalid oracle");
+    require(newPriceId != bytes32(0), "invalid price id");

     address oldOracle = address(PYTH_ORACLE);
     bytes32 oldPriceId = PRICE_ID;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/StableCoin.sol` around lines 154 - 164, The setOracle function validates
newOracle but not the price identifier; add a check in setOracle to
require(newPriceId != bytes32(0), "invalid price id") (or similar) before
assigning PRICE_ID to prevent setting PRICE_ID to zero which would break
getBasePriceInPeggedAsset(), fission(), and transmute functions; keep the rest
of the function (capture oldPriceId, assign PRICE_ID, emit OracleUpdated)
unchanged so the OracleUpdated(oldPriceId, newPriceId) still reflects the
validated value.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant