Skip to content

Add Fate Oracle backend prototype (Chainlink-compatible oracle)#98

Open
sakiluddin-1 wants to merge 4 commits intoStabilityNexus:mainfrom
sakiluddin-1:fate/oracle-backend-prototype
Open

Add Fate Oracle backend prototype (Chainlink-compatible oracle)#98
sakiluddin-1 wants to merge 4 commits intoStabilityNexus:mainfrom
sakiluddin-1:fate/oracle-backend-prototype

Conversation

@sakiluddin-1
Copy link
Copy Markdown

@sakiluddin-1 sakiluddin-1 commented Mar 31, 2026

Overview
This PR adds a prototype backend oracle system for Fate Protocol, implementing on-chain price derivation using bull/bear token dynamics. The design avoids external dependencies and derives prices directly from pool state (reserves & supply), making it trust-minimized and composable.


Key Features

  • Chainlink-style interface (getLatestPrice, getLatestRoundData)
  • Round-based price tracking
  • On-chain price derivation from bull/bear reserves
  • Edge case handling (low liquidity, zero reserves)

Testing

  • Unit and fuzz tests for numerical correctness
  • Validation of edge cases and precision safety

Structure

oracle-prototype/
 ├── src/
 ├── test/
 ├── script/
 └── foundry.toml

Note

This is a prototype implementation based on assumptions, as the original backend contracts are not publicly available.

Summary by CodeRabbit

  • New Features

    • Added an on-chain Fate Protocol oracle, adapter, mock pool, and a runnable deployment/test script.
  • Tests

    • Large, comprehensive test suite validating oracle pricing, edge cases, fuzzing, utilities, and Foundry integrations.
  • Chores

    • Initialized Foundry config, CI workflows, and included the Forge standard library and supporting tooling.
  • Documentation

    • Added README and usage guidance for the backend prototype.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 31, 2026

Walkthrough

Adds an oracle backend prototype with Foundry project scaffolding, a vendored forge-std submodule (sources, tests, tooling), CI workflows, README/license/docs, Solidity oracle + adapter + mocks, extensive std libraries and tests, fixtures, a deployment script, and config files.

Changes

Cohort / File(s) Summary
Repo & Foundry config
/.gitignore, oracle_backend_prototype/.gitignore, oracle_backend_prototype/foundry.toml, oracle_backend_prototype/.gitmodules
Project-level ignore rules, Foundry configuration, and submodule registration for lib/forge-std.
CI & automation
oracle_backend_prototype/.github/workflows/test.yml, oracle_backend_prototype/lib/forge-std/.github/workflows/ci.yml, oracle_backend_prototype/lib/forge-std/.github/workflows/sync.yml, oracle_backend_prototype/lib/forge-std/.github/dependabot.yml, oracle_backend_prototype/lib/forge-std/.github/CODEOWNERS
Adds CI workflows for build/test, release-branch sync, Dependabot config, and CODEOWNERS for the vendored stdlib.
Docs & licensing
oracle_backend_prototype/README.md, oracle_backend_prototype/lib/forge-std/README.md, oracle_backend_prototype/lib/forge-std/CONTRIBUTING.md, .../RELEASE_CHECKLIST.md, .../LICENSE-*
Adds README describing oracle design, forge-std docs, contribution/release guidance, and license files.
Forge-std core & build support
oracle_backend_prototype/lib/forge-std/src/Base.sol, .../Script.sol, .../Test.sol, .../console.sol, .../console2.sol, .../foundry.toml, .../package.json, .../scripts/vm.py, .../.gitattributes, .../.gitignore
Adds base contracts, script/test bases, console logging, Foundry config and package metadata, and a Python generator script for Vm.sol from cheatcodes.
Forge-std libraries & utilities
oracle_backend_prototype/lib/forge-std/src/Std*.sol, oracle_backend_prototype/lib/forge-std/src/LibVariable.sol
Large set of new standard libraries (assertions, chains, cheats, json/toml, math, storage, utils, style, constants, errors, invariant support) and a typed LibVariable implementation.
Interfaces
oracle_backend_prototype/lib/forge-std/src/interfaces/*, oracle_backend_prototype/lib/forge-std/src/interfaces/IMulticall3.sol
Adds many standard interfaces (ERC20/721/1155/4626/6909/7540/7575, IERC165) and a Multicall3 interface.
Forge-std tests & fixtures
oracle_backend_prototype/lib/forge-std/test/*.t.sol, .../test/compilation/*, .../test/fixtures/*
Comprehensive unit/fuzz tests for the std libraries, compilation targets, and JSON/TOML/broadcast fixtures.
Oracle contracts & adapter
oracle_backend_prototype/src/FateOracle.sol, oracle_backend_prototype/src/FateOracleAdapter.sol, oracle_backend_prototype/src/interfaces/IFateOracle.sol
Implements FateOracle (price computation, rounds, staleness checks), Chainlink-style adapter, and the IFateOracle interface.
Mocks, pool & script
oracle_backend_prototype/src/mocks/MockPool.sol, oracle_backend_prototype/src/MakePool.sol, oracle_backend_prototype/script/DeployAndTest.s.sol
Adds MockPool and a MockPool-like pool contract for feeding oracle inputs plus a Foundry script to deploy and exercise the oracle.
Oracle tests
oracle_backend_prototype/test/FateOracleTest.t.sol
Adds unit and fuzz tests validating price computation, zero-supply/no-liquidity reverts, round increments, and stale-data behavior.
Misc files
.gitignore.save
Adds a saved .gitignore snapshot containing broader ignore patterns (no code changes).

Sequence Diagram(s)

sequenceDiagram
    participant Script as Deploy Script
    participant Pool as MockPool
    participant Oracle as FateOracle
    participant Console as console.log

    Script->>Pool: deploy & setState(reserves,supplies,volumes)
    Script->>Oracle: deploy FateOracle(pool.address)
    Script->>Oracle: call updatePrice()
    Oracle->>Pool: getState()
    Oracle-->Oracle: computePrice() (bull/bear prices, weighted avg)
    Oracle-->>Script: store round(price,timestamp)
    Script->>Oracle: getLatestPrice()
    Script->>Console: console.log(price)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

Solidity Lang, Python Lang, Documentation

"🐰
I hopped through code and tests so bright,
Rounds and reserves in the pale moonlight,
Mock pools feeding oracles through the night,
Foundry scripts hum — the protocol's right!"

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

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 21

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.gitignore:
- Around line 42-46: The .gitignore entries use the wrong path prefix (patterns
like "oracle-prototype/cache/", "oracle-prototype/out/",
"oracle-prototype/broadcast/", "oracle-prototype/lib/") so they don’t match this
repo’s directory "oracle_backend_prototype"; update those ignore patterns to the
correct prefix ("oracle_backend_prototype/cache/",
"oracle_backend_prototype/out/", "oracle_backend_prototype/broadcast/",
"oracle_backend_prototype/lib/") or add equivalent rules for both prefixes to
ensure generated artifacts are ignored.

In `@oracle_backend_prototype/.github/workflows/test.yml`:
- Around line 1-38: The workflow named "CI" (job "check") is placed in the wrong
workflow directory and lacks working-directory for Forge commands; move the
workflow file into the repository's root workflows directory so GitHub Actions
will auto-trigger, and update the "Run Forge fmt", "Run Forge build", and "Run
Forge tests" steps to include a working-directory that points to the Foundry
project (or use env FOUNDRY_PROFILE) so forge commands run in the correct
subproject; keep job name "check" and the existing steps but set
working-directory for the three forge steps and ensure permissions remain as
defined.

In `@oracle_backend_prototype/lib/forge-std/.gitignore`:
- Around line 1-4: The repository declares lib/forge-std as a submodule in
.gitmodules but the files are tracked as regular files and the submodule
directory lacks a .git, so either remove the .gitmodules entry for lib/forge-std
and commit the directory contents as normal files, or convert the tracked
directory to a proper submodule by removing the tracked files from the index,
adding the submodule reference, and running git submodule update --init to
restore the lib/forge-std/.git metadata; specifically target the .gitmodules
entry for lib/forge-std and the lib/forge-std directory when making the change
and ensure the index mode becomes 160000 for the submodule case or remove the
.gitmodules entry for the non-submodule case.

In `@oracle_backend_prototype/lib/forge-std/LICENSE-MIT`:
- Around line 24-25: The MIT license text in LICENSE-MIT is corrupted on the
sentence spanning the lines with "IN CONNECTION WITH THE SOFTWARE O THE USE OR
OTHER DEALINGS IN THE SOFTWARE.R"; replace that corrupted fragment with the
canonical MIT disclaimer sentence: "IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE." Ensure the
replacement preserves surrounding punctuation and line wrapping consistent with
the rest of LICENSE-MIT.

In `@oracle_backend_prototype/lib/forge-std/src/interfaces/IERC7540.sol`:
- Around line 101-103: The RedeemRequest event currently declares the last
parameter as uint256 assets which violates ERC-7540; update the event
declaration for RedeemRequest to rename the final parameter from assets to
shares (i.e., event RedeemRequest(address indexed controller, address indexed
owner, uint256 indexed requestId, address sender, uint256 shares)) so the event
signature and ABI match the ERC-7540 spec and downstream integrations; search
for usages of RedeemRequest in the codebase (emit RedeemRequest(...)) and update
any emit calls and tests to use the shares parameter name if they reference it
by name.

In `@oracle_backend_prototype/lib/forge-std/test/Config.t.sol`:
- Around line 166-167: The test currently flips the writeUpdatesBackToFile flag
by writing directly to storage via vm.store (hard-coded slot 5), which breaks if
the Config storage layout changes; add a test-only harness API instead:
implement a ConfigHarness (or extend the existing Config in tests) that exposes
a setter like setWriteUpdatesBackToFile(bool) which directly sets the named
state variable, and update the tests (where vm.store(address(config),
bytes32(uint256(5)), ...) is used) to call
ConfigHarness.setWriteUpdatesBackToFile(true/false) so the test no longer relies
on hard-coded slot numbers and remains robust to storage reordering.

In `@oracle_backend_prototype/README.md`:
- Around line 56-58: Replace the incorrect Forge command "forge compile" with
the correct "forge build" wherever it appears in the README (specifically change
the line containing "forge compile" to "forge build") and run a quick grep for
the exact string "forge compile" to update any other occurrences.

In `@oracle_backend_prototype/src/FateOracle.sol`:
- Around line 81-95: getLatestPrice currently returns
rounds[latestRoundId].price without a staleness check, allowing callers to
receive stale data unlike getLatestRoundData which enforces STALE_TIME; update
getLatestPrice to require(latestRoundId > 0, "No data") as now, then load
RoundData r = rounds[latestRoundId] and add the same freshness guard
require(block.timestamp - r.timestamp <= STALE_TIME, "Stale price") before
returning r.price so both read APIs have consistent validation (use the same
latestRoundId, rounds mapping, RoundData type and STALE_TIME constant).
- Around line 15-35: The state variable pool is only set in the constructor and
should be marked immutable to save gas and enforce immutability; update the
declaration of pool to be immutable (e.g., change address public pool to address
public immutable pool) and keep the existing assignment in the constructor
(constructor(address _pool) { require(_pool != address(0), "Invalid pool"); pool
= _pool; }) so no other logic changes are needed; reference symbols: pool and
the constructor.
- Around line 65-75: Add an event declaration (e.g., NewRound or PriceUpdated)
and emit it from updatePrice() after writing rounds[latestRoundId] so off-chain
consumers can index changes; include the unique identifiers and useful data such
as roundId (latestRoundId), price, and timestamp (block.timestamp) in the event
payload, ensure the event is declared alongside the contract state (near
RoundData and rounds) and that updatePrice() calls emit with the same values
assigned to rounds[latestRoundId].
- Around line 47-57: The price math currently divides reserves by supply early
(bullPrice/bearPrice), losing precision; change the order so you multiply
reserves by their weights first and then divide by supply and 100 to avoid
truncation. Concretely, replace uses of bullPrice and bearPrice with expressions
like (bullReserve * bullWeight) / (bullSupply * 100) and (bearReserve *
bearWeight) / (bearSupply * 100), then sum those to compute weightedPrice;
ensure you use uint256 for all intermediate calculations to avoid overflow.

In `@oracle_backend_prototype/src/FateOracleAdapter.sol`:
- Around line 29-31: The adapter currently proxies latestRoundData() to
oracle.getLatestRoundData() but lacks the standard Chainlink
AggregatorV3Interface version() entry; add a public/external view function named
version() that returns uint256 and simply returns oracle.version() (or a
compatible constant if underlying oracle lacks it) so the contract fully
implements the AggregatorV3Interface and is compatible with integrations
expecting version().
- Line 11: The state variable IFateOracle oracle is assigned only in the
constructor and should be marked immutable to save gas and prevent later
modification; update the declaration to use the immutable keyword (e.g.,
"IFateOracle public immutable oracle") and ensure the existing constructor
continues to initialize oracle exactly once (no other changes needed beyond the
declaration), referencing the IFateOracle type and oracle symbol in
FateOracleAdapter.sol.

In `@oracle_backend_prototype/src/interfaces/IFateOracle.sol`:
- Around line 8-9: Add NatSpec `@return` tags for the getLatestRoundData function
to document each returned value: describe roundId, answer, startedAt, updatedAt,
and answeredInRound using `@return` annotations so consumers know the semantics of
each field (e.g., round identifier, latest answer, timestamp when round started,
timestamp when updated, and the round in which the answer was computed). Update
the function declaration comment block above getLatestRoundData to include these
`@return` lines without changing the function signature.
- Line 2: Update the Solidity pragma in IFateOracle.sol: replace the restrictive
declaration "pragma solidity ^0.8.30;" with a broader compatible range such as
"pragma solidity ^0.8.20;" so the contract (IFateOracle) matches the project's
other files (e.g., DeployAndTest.s.sol) and increases tooling/chain
compatibility.

In `@oracle_backend_prototype/src/MakePool.sol`:
- Around line 9-24: Declare the owner variable as immutable to avoid extra
SLOADs: change the declaration of owner to be `immutable` (e.g., `address public
immutable owner`) and keep the constructor assignment (`owner = msg.sender;`);
then ensure any `onlyOwner` modifier or permission checks continue to reference
the same `owner` identifier (no other code changes required besides the
declaration) so the contract benefits from cheaper reads.
- Around line 47-49: The setState function in MockPool currently blocks zero
supplies via the require in setState, which prevents testing the oracle's
zero-supply failure path; either remove that require from setState to allow
_bullSupply and _bearSupply to be zero, or add a new onlyOwner method (e.g.,
setStateUnsafe) that mirrors setState's behavior but omits the require so tests
can configure the zero-supply edge case without reverting inside MockPool;
update callers/tests to use setStateUnsafe for edge-case tests and keep normal
setState behavior if you prefer to retain a guarded setter.

In `@oracle_backend_prototype/src/mocks/MockPool.sol`:
- Around line 12-19: The setState function allows nonsensical states that can
cause division-by-zero or invalid oracle results; add input validation at the
start of setState to require that whenever bullReserve > 0 then bullSupply > 0
and whenever bearReserve > 0 then bearSupply > 0 (use require to revert on
invalid inputs), and optionally add sanity checks such as ensuring reserves and
supplies are within expected ranges (e.g., non-zero together or not absurdly
disparate) to prevent malformed test setups; update the checks around the
setState function and the variables bullReserve, bearReserve, bullSupply,
bearSupply accordingly.
- Around line 12-19: The setState function in MockPool allows anyone to change
pool state; restrict it by inheriting Ownable (or adding an owner and onlyOwner
modifier) and apply onlyOwner to setState so only the contract owner can call
it; update the contract constructor to set the owner (or call Ownable's
constructor) and adjust any tests to call setState from the owner account or use
transferOwnership as needed.
- Around line 12-19: The setState function mutates six state variables
(bullReserve, bearReserve, bullSupply, bearSupply, bullVolume, bearVolume) but
emits no event; add a descriptive event (e.g., StateUpdated or SetState) to the
contract and emit it at the end of setState with the new values so tests and
logs can verify changes; update the contract to declare the event signature and
call emit StateUpdated(bullReserve, bearReserve, bullSupply, bearSupply,
bullVolume, bearVolume) inside setState.

In `@oracle_backend_prototype/test/FateOracleTest.t.sol`:
- Around line 51-64: The tests testRevertZeroSupply and testRevertNoLiquidity
use vm.expectRevert() with no reason; update each to expect the specific revert
reason emitted by oracle.updatePrice() instead. Inspect the Oracle contract to
find the exact revert strings (e.g., "ZERO_SUPPLY" or "NO_LIQUIDITY" or whatever
oracle.updatePrice() uses), then replace vm.expectRevert() with
vm.expectRevert(bytes("EXPECTED_REASON")) immediately before calling
oracle.updatePrice() in both tests (referencing testRevertZeroSupply,
testRevertNoLiquidity, oracle.updatePrice, and pool.setState to locate the
code).
🪄 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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 38bf0c0e-5bfc-461c-b2e2-4964a93391a2

📥 Commits

Reviewing files that changed from the base of the PR and between fbd27aa and be7fb23.

⛔ Files ignored due to path filters (1)
  • oracle_backend_prototype/foundry.lock is excluded by !**/*.lock
📒 Files selected for processing (81)
  • .gitignore
  • oracle_backend_prototype/.github/workflows/test.yml
  • oracle_backend_prototype/.gitignore
  • oracle_backend_prototype/.gitmodules
  • oracle_backend_prototype/README.md
  • oracle_backend_prototype/foundry.toml
  • oracle_backend_prototype/lib/forge-std/.gitattributes
  • oracle_backend_prototype/lib/forge-std/.github/CODEOWNERS
  • oracle_backend_prototype/lib/forge-std/.github/dependabot.yml
  • oracle_backend_prototype/lib/forge-std/.github/workflows/ci.yml
  • oracle_backend_prototype/lib/forge-std/.github/workflows/sync.yml
  • oracle_backend_prototype/lib/forge-std/.gitignore
  • oracle_backend_prototype/lib/forge-std/CONTRIBUTING.md
  • oracle_backend_prototype/lib/forge-std/LICENSE-APACHE
  • oracle_backend_prototype/lib/forge-std/LICENSE-MIT
  • oracle_backend_prototype/lib/forge-std/README.md
  • oracle_backend_prototype/lib/forge-std/RELEASE_CHECKLIST.md
  • oracle_backend_prototype/lib/forge-std/foundry.toml
  • oracle_backend_prototype/lib/forge-std/package.json
  • oracle_backend_prototype/lib/forge-std/scripts/vm.py
  • oracle_backend_prototype/lib/forge-std/src/Base.sol
  • oracle_backend_prototype/lib/forge-std/src/Config.sol
  • oracle_backend_prototype/lib/forge-std/src/LibVariable.sol
  • oracle_backend_prototype/lib/forge-std/src/Script.sol
  • oracle_backend_prototype/lib/forge-std/src/StdAssertions.sol
  • oracle_backend_prototype/lib/forge-std/src/StdChains.sol
  • oracle_backend_prototype/lib/forge-std/src/StdCheats.sol
  • oracle_backend_prototype/lib/forge-std/src/StdConfig.sol
  • oracle_backend_prototype/lib/forge-std/src/StdConstants.sol
  • oracle_backend_prototype/lib/forge-std/src/StdError.sol
  • oracle_backend_prototype/lib/forge-std/src/StdInvariant.sol
  • oracle_backend_prototype/lib/forge-std/src/StdJson.sol
  • oracle_backend_prototype/lib/forge-std/src/StdMath.sol
  • oracle_backend_prototype/lib/forge-std/src/StdStorage.sol
  • oracle_backend_prototype/lib/forge-std/src/StdStyle.sol
  • oracle_backend_prototype/lib/forge-std/src/StdToml.sol
  • oracle_backend_prototype/lib/forge-std/src/StdUtils.sol
  • oracle_backend_prototype/lib/forge-std/src/Test.sol
  • oracle_backend_prototype/lib/forge-std/src/Vm.sol
  • oracle_backend_prototype/lib/forge-std/src/console.sol
  • oracle_backend_prototype/lib/forge-std/src/console2.sol
  • oracle_backend_prototype/lib/forge-std/src/interfaces/IERC1155.sol
  • oracle_backend_prototype/lib/forge-std/src/interfaces/IERC165.sol
  • oracle_backend_prototype/lib/forge-std/src/interfaces/IERC20.sol
  • oracle_backend_prototype/lib/forge-std/src/interfaces/IERC4626.sol
  • oracle_backend_prototype/lib/forge-std/src/interfaces/IERC6909.sol
  • oracle_backend_prototype/lib/forge-std/src/interfaces/IERC721.sol
  • oracle_backend_prototype/lib/forge-std/src/interfaces/IERC7540.sol
  • oracle_backend_prototype/lib/forge-std/src/interfaces/IERC7575.sol
  • oracle_backend_prototype/lib/forge-std/src/interfaces/IMulticall3.sol
  • oracle_backend_prototype/lib/forge-std/src/safeconsole.sol
  • oracle_backend_prototype/lib/forge-std/test/CommonBase.t.sol
  • oracle_backend_prototype/lib/forge-std/test/Config.t.sol
  • oracle_backend_prototype/lib/forge-std/test/LibVariable.t.sol
  • oracle_backend_prototype/lib/forge-std/test/StdAssertions.t.sol
  • oracle_backend_prototype/lib/forge-std/test/StdChains.t.sol
  • oracle_backend_prototype/lib/forge-std/test/StdCheats.t.sol
  • oracle_backend_prototype/lib/forge-std/test/StdConstants.t.sol
  • oracle_backend_prototype/lib/forge-std/test/StdError.t.sol
  • oracle_backend_prototype/lib/forge-std/test/StdJson.t.sol
  • oracle_backend_prototype/lib/forge-std/test/StdMath.t.sol
  • oracle_backend_prototype/lib/forge-std/test/StdStorage.t.sol
  • oracle_backend_prototype/lib/forge-std/test/StdStyle.t.sol
  • oracle_backend_prototype/lib/forge-std/test/StdToml.t.sol
  • oracle_backend_prototype/lib/forge-std/test/StdUtils.t.sol
  • oracle_backend_prototype/lib/forge-std/test/Vm.t.sol
  • oracle_backend_prototype/lib/forge-std/test/compilation/CompilationScript.sol
  • oracle_backend_prototype/lib/forge-std/test/compilation/CompilationScriptBase.sol
  • oracle_backend_prototype/lib/forge-std/test/compilation/CompilationTest.sol
  • oracle_backend_prototype/lib/forge-std/test/compilation/CompilationTestBase.sol
  • oracle_backend_prototype/lib/forge-std/test/fixtures/broadcast.log.json
  • oracle_backend_prototype/lib/forge-std/test/fixtures/config.toml
  • oracle_backend_prototype/lib/forge-std/test/fixtures/test.json
  • oracle_backend_prototype/lib/forge-std/test/fixtures/test.toml
  • oracle_backend_prototype/script/DeployAndTest.s.sol
  • oracle_backend_prototype/src/FateOracle.sol
  • oracle_backend_prototype/src/FateOracleAdapter.sol
  • oracle_backend_prototype/src/MakePool.sol
  • oracle_backend_prototype/src/interfaces/IFateOracle.sol
  • oracle_backend_prototype/src/mocks/MockPool.sol
  • oracle_backend_prototype/test/FateOracleTest.t.sol

Comment thread .gitignore Outdated
Comment on lines +1 to +38
name: CI

permissions: {}

on:
push:
pull_request:
workflow_dispatch:

env:
FOUNDRY_PROFILE: ci

jobs:
check:
name: Foundry project
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v5
with:
persist-credentials: false
submodules: recursive

- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1

- name: Show Forge version
run: forge --version

- name: Run Forge fmt
run: forge fmt --check

- name: Run Forge build
run: forge build --sizes

- name: Run Forge tests
run: forge test -vvv
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 | 🟠 Major

Workflow placement/execution context is likely incorrect for CI.

Line 1-38 defines a valid workflow, but at path oracle_backend_prototype/.github/workflows/test.yml it will not be auto-triggered by GitHub Actions (must be under repository-root .github/workflows/). Also, Line 31/35/38 run Forge commands without setting working-directory, which can fail in a monorepo layout.

Suggested fix
 jobs:
   check:
     name: Foundry project
     runs-on: ubuntu-latest
+    defaults:
+      run:
+        working-directory: oracle_backend_prototype
     permissions:
       contents: read

Also move this file to: .github/workflows/test.yml at repository root.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
name: CI
permissions: {}
on:
push:
pull_request:
workflow_dispatch:
env:
FOUNDRY_PROFILE: ci
jobs:
check:
name: Foundry project
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v5
with:
persist-credentials: false
submodules: recursive
- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
- name: Show Forge version
run: forge --version
- name: Run Forge fmt
run: forge fmt --check
- name: Run Forge build
run: forge build --sizes
- name: Run Forge tests
run: forge test -vvv
name: CI
permissions: {}
on:
push:
pull_request:
workflow_dispatch:
env:
FOUNDRY_PROFILE: ci
jobs:
check:
name: Foundry project
runs-on: ubuntu-latest
defaults:
run:
working-directory: oracle_backend_prototype
permissions:
contents: read
steps:
- uses: actions/checkout@v5
with:
persist-credentials: false
submodules: recursive
- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
- name: Show Forge version
run: forge --version
- name: Run Forge fmt
run: forge fmt --check
- name: Run Forge build
run: forge build --sizes
- name: Run Forge tests
run: forge test -vvv
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@oracle_backend_prototype/.github/workflows/test.yml` around lines 1 - 38, The
workflow named "CI" (job "check") is placed in the wrong workflow directory and
lacks working-directory for Forge commands; move the workflow file into the
repository's root workflows directory so GitHub Actions will auto-trigger, and
update the "Run Forge fmt", "Run Forge build", and "Run Forge tests" steps to
include a working-directory that points to the Foundry project (or use env
FOUNDRY_PROFILE) so forge commands run in the correct subproject; keep job name
"check" and the existing steps but set working-directory for the three forge
steps and ensure permissions remain as defined.

Comment on lines +1 to +4
cache/
out/
.vscode
.idea
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 | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Check if forge-std is properly configured as a submodule

# Check if .gitmodules exists and contains forge-std
if [ -f "oracle_backend_prototype/.gitmodules" ]; then
    echo "=== .gitmodules content ==="
    cat oracle_backend_prototype/.gitmodules
fi

# Check git submodule status
echo -e "\n=== Git submodule status ==="
git submodule status oracle_backend_prototype/lib/forge-std || echo "Not a submodule"

# Check if files are tracked in git index as regular files
echo -e "\n=== Git index status for forge-std files ==="
git ls-files --stage oracle_backend_prototype/lib/forge-std/.gitignore
git ls-files --stage oracle_backend_prototype/lib/forge-std/.github/dependabot.yml

Repository: StabilityNexus/Fate-EVM-Frontend

Length of output: 488


🏁 Script executed:

# Check if .git directory exists in forge-std (indicator of proper initialization)
if [ -d "oracle_backend_prototype/lib/forge-std/.git" ]; then
    echo "forge-std has .git directory (properly initialized submodule)"
else
    echo "forge-std does NOT have .git directory"
fi

# Check the root .git/config to see submodule configuration
echo -e "\n=== Submodule entry in .git/config ==="
git config --file oracle_backend_prototype/.git/config --get-regexp submodule || echo "No submodule config found"

# Check git ls-files for the path itself (160000 would indicate submodule)
echo -e "\n=== Checking if forge-std directory is tracked as submodule ==="
git ls-files -s oracle_backend_prototype/lib/forge-std | head -1

Repository: StabilityNexus/Fate-EVM-Frontend

Length of output: 349


Remove .gitmodules entry or properly initialize the forge-std submodule.

The .gitmodules file declares lib/forge-std as a Git submodule, but the files are being tracked as regular files in the repository index (mode 100644) instead of as a submodule reference (mode 160000). Additionally, the submodule directory lacks a .git directory, indicating it was never properly initialized. Either remove the submodule declaration from .gitmodules if you intend to commit these files directly, or properly initialize the submodule with git submodule update --init to align the configuration with the actual repository state.

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

In `@oracle_backend_prototype/lib/forge-std/.gitignore` around lines 1 - 4, The
repository declares lib/forge-std as a submodule in .gitmodules but the files
are tracked as regular files and the submodule directory lacks a .git, so either
remove the .gitmodules entry for lib/forge-std and commit the directory contents
as normal files, or convert the tracked directory to a proper submodule by
removing the tracked files from the index, adding the submodule reference, and
running git submodule update --init to restore the lib/forge-std/.git metadata;
specifically target the .gitmodules entry for lib/forge-std and the
lib/forge-std directory when making the change and ensure the index mode becomes
160000 for the submodule case or remove the .gitmodules entry for the
non-submodule case.

Comment on lines +24 to +25
IN CONNECTION WITH THE SOFTWARE O THE USE OR OTHER
DEALINGS IN THE SOFTWARE.R
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 | 🟠 Major

MIT license text appears corrupted.

Line 24–25 contains typos (O / trailing R) and does not match the canonical MIT disclaimer sentence. This can create compliance ambiguity for redistributed code.

Suggested fix
-IN CONNECTION WITH THE SOFTWARE O THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.R
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
IN CONNECTION WITH THE SOFTWARE O THE USE OR OTHER
DEALINGS IN THE SOFTWARE.R
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@oracle_backend_prototype/lib/forge-std/LICENSE-MIT` around lines 24 - 25, The
MIT license text in LICENSE-MIT is corrupted on the sentence spanning the lines
with "IN CONNECTION WITH THE SOFTWARE O THE USE OR OTHER DEALINGS IN THE
SOFTWARE.R"; replace that corrupted fragment with the canonical MIT disclaimer
sentence: "IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE." Ensure the replacement preserves surrounding
punctuation and line wrapping consistent with the rest of LICENSE-MIT.

Comment on lines +101 to +103
event RedeemRequest(
address indexed controller, address indexed owner, uint256 indexed requestId, address sender, uint256 assets
);
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 | 🟠 Major

🧩 Analysis chain

🌐 Web query:

In the ERC-7540 specification, what is the exact RedeemRequest event signature, and is its amount parameter defined in shares or assets?

💡 Result:

The exact RedeemRequest event signature in the ERC-7540 specification is: event RedeemRequest( address indexed controller, address indexed owner, uint256 indexed requestId, address sender, uint256 shares ); The amount parameter is "shares", not assets.

Citations:


Correct RedeemRequest event parameter from assets to shares per ERC-7540 specification.

The event at lines 101–103 declares RedeemRequest(..., uint256 assets), but ERC-7540 specifies the parameter must be uint256 shares. This creates a spec violation that breaks integration expectations and event semantics. Change assets to shares to align with the standard.

Current code (incorrect)
event RedeemRequest(
    address indexed controller, address indexed owner, uint256 indexed requestId, address sender, uint256 assets
);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@oracle_backend_prototype/lib/forge-std/src/interfaces/IERC7540.sol` around
lines 101 - 103, The RedeemRequest event currently declares the last parameter
as uint256 assets which violates ERC-7540; update the event declaration for
RedeemRequest to rename the final parameter from assets to shares (i.e., event
RedeemRequest(address indexed controller, address indexed owner, uint256 indexed
requestId, address sender, uint256 shares)) so the event signature and ABI match
the ERC-7540 spec and downstream integrations; search for usages of
RedeemRequest in the codebase (emit RedeemRequest(...)) and update any emit
calls and tests to use the shares parameter name if they reference it by name.

Comment on lines +8 to +9
/// @notice Returns Chainlink-style round data
function getLatestRoundData() external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);
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.

🧹 Nitpick | 🔵 Trivial

Add NatSpec documentation for return values.

For a Chainlink-compatible interface, documenting the return values helps consumers understand the expected semantics.

📝 Suggested documentation
-    /// `@notice` Returns Chainlink-style round data
+    /// `@notice` Returns Chainlink-style round data
+    /// `@return` roundId The round ID
+    /// `@return` answer The price answer (scaled by decimals)
+    /// `@return` startedAt Timestamp when the round started
+    /// `@return` updatedAt Timestamp when the answer was computed
+    /// `@return` answeredInRound The round ID in which the answer was computed
     function getLatestRoundData() external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@oracle_backend_prototype/src/interfaces/IFateOracle.sol` around lines 8 - 9,
Add NatSpec `@return` tags for the getLatestRoundData function to document each
returned value: describe roundId, answer, startedAt, updatedAt, and
answeredInRound using `@return` annotations so consumers know the semantics of
each field (e.g., round identifier, latest answer, timestamp when round started,
timestamp when updated, and the round in which the answer was computed). Update
the function declaration comment block above getLatestRoundData to include these
`@return` lines without changing the function signature.

Comment on lines +9 to +24
address public owner;
uint256 public bullReserve; // total funds in bull vault
uint256 public bearReserve; // total funds in bear vault
uint256 public bullSupply; // total supply of bull tokens
uint256 public bearSupply; // total supply of bear tokens
uint256 public bullVolume; // total volume of bull trades
uint256 public bearVolume; // total volume of bear trades
uint256 public lastUpdated; // timestamp of last update

// =========================
// CONSTRUCTOR
// =========================

constructor() {
owner = msg.sender;
}
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.

🧹 Nitpick | 🔵 Trivial

Use immutable for owner.

owner is assigned once in the constructor and never changes. Keeping it in storage adds an avoidable read to every onlyOwner check.

♻️ Proposed change
-    address public owner;
+    address public immutable owner;
As per coding guidelines, "Ensure immutability is used appropriately (e.g., `immutable` and `constant` where applicable)."
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
address public owner;
uint256 public bullReserve; // total funds in bull vault
uint256 public bearReserve; // total funds in bear vault
uint256 public bullSupply; // total supply of bull tokens
uint256 public bearSupply; // total supply of bear tokens
uint256 public bullVolume; // total volume of bull trades
uint256 public bearVolume; // total volume of bear trades
uint256 public lastUpdated; // timestamp of last update
// =========================
// CONSTRUCTOR
// =========================
constructor() {
owner = msg.sender;
}
address public immutable owner;
uint256 public bullReserve; // total funds in bull vault
uint256 public bearReserve; // total funds in bear vault
uint256 public bullSupply; // total supply of bull tokens
uint256 public bearSupply; // total supply of bear tokens
uint256 public bullVolume; // total volume of bull trades
uint256 public bearVolume; // total volume of bear trades
uint256 public lastUpdated; // timestamp of last update
// =========================
// CONSTRUCTOR
// =========================
constructor() {
owner = msg.sender;
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@oracle_backend_prototype/src/MakePool.sol` around lines 9 - 24, Declare the
owner variable as immutable to avoid extra SLOADs: change the declaration of
owner to be `immutable` (e.g., `address public immutable owner`) and keep the
constructor assignment (`owner = msg.sender;`); then ensure any `onlyOwner`
modifier or permission checks continue to reference the same `owner` identifier
(no other code changes required besides the declaration) so the contract
benefits from cheaper reads.

Comment on lines +47 to +49
function setState(uint256 _bullReserve, uint256 _bearReserve, uint256 _bullSupply, uint256 _bearSupply, uint256 _bullVolume, uint256 _bearVolume) external onlyOwner {
require(_bullSupply > 0 && _bearSupply > 0, "Invalid supply");

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 | 🟠 Major

Don't block zero-supply states in the mock.

Line 48 prevents configuring the exact zero-supply path the oracle is supposed to defend against. That means a revert test here will stop in MockPool instead of exercising FateOracle's failure handling. Allow zero supplies in this mock, or add a separate unsafe setter dedicated to edge-case tests.

🧪 Minimal fix
-        require(_bullSupply > 0 && _bearSupply > 0, "Invalid supply");
As per coding guidelines, "Ensure failure paths and revert scenarios are explicitly handled and validated."
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function setState(uint256 _bullReserve, uint256 _bearReserve, uint256 _bullSupply, uint256 _bearSupply, uint256 _bullVolume, uint256 _bearVolume) external onlyOwner {
require(_bullSupply > 0 && _bearSupply > 0, "Invalid supply");
function setState(uint256 _bullReserve, uint256 _bearReserve, uint256 _bullSupply, uint256 _bearSupply, uint256 _bullVolume, uint256 _bearVolume) external onlyOwner {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@oracle_backend_prototype/src/MakePool.sol` around lines 47 - 49, The setState
function in MockPool currently blocks zero supplies via the require in setState,
which prevents testing the oracle's zero-supply failure path; either remove that
require from setState to allow _bullSupply and _bearSupply to be zero, or add a
new onlyOwner method (e.g., setStateUnsafe) that mirrors setState's behavior but
omits the require so tests can configure the zero-supply edge case without
reverting inside MockPool; update callers/tests to use setStateUnsafe for
edge-case tests and keep normal setState behavior if you prefer to retain a
guarded setter.

Comment on lines +12 to +19
function setState( uint256 _bullReserve, uint256 _bearReserve, uint256 _bullSupply, uint256 _bearSupply, uint256 _bullVolume, uint256 _bearVolume) external {
bullReserve = _bullReserve;
bearReserve = _bearReserve;
bullSupply = _bullSupply;
bearSupply = _bearSupply;
bullVolume = _bullVolume;
bearVolume = _bearVolume;
}
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.

🧹 Nitpick | 🔵 Trivial

Consider adding input validation for edge cases.

The setState function accepts all parameters without validation. While a mock may intentionally allow extreme values for testing edge cases, consider validating at least:

  • That supply values are non-zero when reserves are non-zero (to prevent division-by-zero in oracle price calculations)
  • That reserve/supply pairs maintain some relationship to avoid nonsensical test states

This would help catch test setup errors early.

🛡️ Optional: Add basic sanity checks
     function setState( uint256 _bullReserve, uint256 _bearReserve, uint256 _bullSupply, uint256 _bearSupply, uint256 _bullVolume, uint256 _bearVolume) external {
+        // Sanity check: if reserves are non-zero, supplies should be too
+        if (_bullReserve > 0) require(_bullSupply > 0, "MockPool: bull supply cannot be zero with non-zero reserve");
+        if (_bearReserve > 0) require(_bearSupply > 0, "MockPool: bear supply cannot be zero with non-zero reserve");
+        
         bullReserve = _bullReserve;
         bearReserve = _bearReserve;
         bullSupply = _bullSupply;
         bearSupply = _bearSupply;
         bullVolume = _bullVolume;
         bearVolume = _bearVolume;
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function setState( uint256 _bullReserve, uint256 _bearReserve, uint256 _bullSupply, uint256 _bearSupply, uint256 _bullVolume, uint256 _bearVolume) external {
bullReserve = _bullReserve;
bearReserve = _bearReserve;
bullSupply = _bullSupply;
bearSupply = _bearSupply;
bullVolume = _bullVolume;
bearVolume = _bearVolume;
}
function setState( uint256 _bullReserve, uint256 _bearReserve, uint256 _bullSupply, uint256 _bearSupply, uint256 _bullVolume, uint256 _bearVolume) external {
// Sanity check: if reserves are non-zero, supplies should be too
if (_bullReserve > 0) require(_bullSupply > 0, "MockPool: bull supply cannot be zero with non-zero reserve");
if (_bearReserve > 0) require(_bearSupply > 0, "MockPool: bear supply cannot be zero with non-zero reserve");
bullReserve = _bullReserve;
bearReserve = _bearReserve;
bullSupply = _bullSupply;
bearSupply = _bearSupply;
bullVolume = _bullVolume;
bearVolume = _bearVolume;
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@oracle_backend_prototype/src/mocks/MockPool.sol` around lines 12 - 19, The
setState function allows nonsensical states that can cause division-by-zero or
invalid oracle results; add input validation at the start of setState to require
that whenever bullReserve > 0 then bullSupply > 0 and whenever bearReserve > 0
then bearSupply > 0 (use require to revert on invalid inputs), and optionally
add sanity checks such as ensuring reserves and supplies are within expected
ranges (e.g., non-zero together or not absurdly disparate) to prevent malformed
test setups; update the checks around the setState function and the variables
bullReserve, bearReserve, bullSupply, bearSupply accordingly.

⚠️ Potential issue | 🟠 Major

Add access control to prevent unauthorized state manipulation.

The setState function lacks access control, allowing anyone to arbitrarily modify the pool's state. While this is a mock contract, unrestricted mutability creates risk:

  • If accidentally deployed or referenced in production contexts, the oracle could be manipulated
  • Tests may inadvertently allow external actors to corrupt mock state in integration scenarios

For a protocol emphasizing "trust-minimized" design, even test infrastructure should demonstrate proper access patterns.

🔒 Proposed fix: Add Ownable access control
 // SPDX-License-Identifier: MIT
 pragma solidity ^0.8.30;
 
+import "@openzeppelin/contracts/access/Ownable.sol";
+
-contract MockPool {
+contract MockPool is Ownable {
     uint256 public bullReserve;
     uint256 public bearReserve;
     uint256 public bullSupply;
     uint256 public bearSupply;
     uint256 public bullVolume;
     uint256 public bearVolume;
 
+    constructor() Ownable(msg.sender) {}
+
-    function setState( uint256 _bullReserve, uint256 _bearReserve, uint256 _bullSupply, uint256 _bearSupply, uint256 _bullVolume, uint256 _bearVolume) external {
+    function setState( uint256 _bullReserve, uint256 _bearReserve, uint256 _bullSupply, uint256 _bearSupply, uint256 _bullVolume, uint256 _bearVolume) external onlyOwner {
         bullReserve = _bullReserve;
         bearReserve = _bearReserve;
         bullSupply = _bullSupply;
         bearSupply = _bearSupply;
         bullVolume = _bullVolume;
         bearVolume = _bearVolume;
     }

As per coding guidelines: "Validate proper access control enforcement (e.g., Ownable, RBAC, role checks)."

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

In `@oracle_backend_prototype/src/mocks/MockPool.sol` around lines 12 - 19, The
setState function in MockPool allows anyone to change pool state; restrict it by
inheriting Ownable (or adding an owner and onlyOwner modifier) and apply
onlyOwner to setState so only the contract owner can call it; update the
contract constructor to set the owner (or call Ownable's constructor) and adjust
any tests to call setState from the owner account or use transferOwnership as
needed.

🧹 Nitpick | 🔵 Trivial

Emit events for state-changing operations.

The setState function modifies all six state variables but does not emit any events. Events improve testability by allowing tests to verify that expected state transitions occurred and provide an audit trail of mock state changes during test execution.

📢 Proposed enhancement: Add state change event
 contract MockPool {
     uint256 public bullReserve;
     uint256 public bearReserve;
     uint256 public bullSupply;
     uint256 public bearSupply;
     uint256 public bullVolume;
     uint256 public bearVolume;
 
+    event StateUpdated(
+        uint256 bullReserve,
+        uint256 bearReserve,
+        uint256 bullSupply,
+        uint256 bearSupply,
+        uint256 bullVolume,
+        uint256 bearVolume
+    );
+
     function setState( uint256 _bullReserve, uint256 _bearReserve, uint256 _bullSupply, uint256 _bearSupply, uint256 _bullVolume, uint256 _bearVolume) external {
         bullReserve = _bullReserve;
         bearReserve = _bearReserve;
         bullSupply = _bullSupply;
         bearSupply = _bearSupply;
         bullVolume = _bullVolume;
         bearVolume = _bearVolume;
+        emit StateUpdated(_bullReserve, _bearReserve, _bullSupply, _bearSupply, _bullVolume, _bearVolume);
     }

As per coding guidelines: "Ensure consistent and correct event emission for all state-changing operations."

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function setState( uint256 _bullReserve, uint256 _bearReserve, uint256 _bullSupply, uint256 _bearSupply, uint256 _bullVolume, uint256 _bearVolume) external {
bullReserve = _bullReserve;
bearReserve = _bearReserve;
bullSupply = _bullSupply;
bearSupply = _bearSupply;
bullVolume = _bullVolume;
bearVolume = _bearVolume;
}
function setState( uint256 _bullReserve, uint256 _bearReserve, uint256 _bullSupply, uint256 _bearSupply, uint256 _bullVolume, uint256 _bearVolume) external {
bullReserve = _bullReserve;
bearReserve = _bearReserve;
bullSupply = _bullSupply;
bearSupply = _bearSupply;
bullVolume = _bullVolume;
bearVolume = _bearVolume;
emit StateUpdated(_bullReserve, _bearReserve, _bullSupply, _bearSupply, _bullVolume, _bearVolume);
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@oracle_backend_prototype/src/mocks/MockPool.sol` around lines 12 - 19, The
setState function mutates six state variables (bullReserve, bearReserve,
bullSupply, bearSupply, bullVolume, bearVolume) but emits no event; add a
descriptive event (e.g., StateUpdated or SetState) to the contract and emit it
at the end of setState with the new values so tests and logs can verify changes;
update the contract to declare the event signature and call emit
StateUpdated(bullReserve, bearReserve, bullSupply, bearSupply, bullVolume,
bearVolume) inside setState.

Comment on lines +51 to +64
function testRevertZeroSupply() public {
pool.setState(1000, 1000, 0, 100, 500, 500);

vm.expectRevert();

oracle.updatePrice();
}

function testRevertNoLiquidity() public {
pool.setState(0, 1000, 100, 100, 500, 500);

vm.expectRevert();

oracle.updatePrice();
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

Use explicit revert reasons in negative tests.

These two tests currently pass on any revert, so they can miss regressions in failure semantics.

Proposed fix
     function testRevertZeroSupply() public {
         pool.setState(1000, 1000, 0, 100, 500, 500);

-        vm.expectRevert();
+        vm.expectRevert("Invalid supply");

         oracle.updatePrice();
     }

     function testRevertNoLiquidity() public {
         pool.setState(0, 1000, 100, 100, 500, 500);

-        vm.expectRevert();
+        vm.expectRevert("No liquidity");

         oracle.updatePrice();
     }

As per coding guidelines "Ensure failure paths and revert scenarios are explicitly handled and validated."

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function testRevertZeroSupply() public {
pool.setState(1000, 1000, 0, 100, 500, 500);
vm.expectRevert();
oracle.updatePrice();
}
function testRevertNoLiquidity() public {
pool.setState(0, 1000, 100, 100, 500, 500);
vm.expectRevert();
oracle.updatePrice();
function testRevertZeroSupply() public {
pool.setState(1000, 1000, 0, 100, 500, 500);
vm.expectRevert("Invalid supply");
oracle.updatePrice();
}
function testRevertNoLiquidity() public {
pool.setState(0, 1000, 100, 100, 500, 500);
vm.expectRevert("No liquidity");
oracle.updatePrice();
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@oracle_backend_prototype/test/FateOracleTest.t.sol` around lines 51 - 64, The
tests testRevertZeroSupply and testRevertNoLiquidity use vm.expectRevert() with
no reason; update each to expect the specific revert reason emitted by
oracle.updatePrice() instead. Inspect the Oracle contract to find the exact
revert strings (e.g., "ZERO_SUPPLY" or "NO_LIQUIDITY" or whatever
oracle.updatePrice() uses), then replace vm.expectRevert() with
vm.expectRevert(bytes("EXPECTED_REASON")) immediately before calling
oracle.updatePrice() in both tests (referencing testRevertZeroSupply,
testRevertNoLiquidity, oracle.updatePrice, and pool.setState to locate the
code).

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (1)
.gitignore (1)

42-46: ⚠️ Potential issue | 🟡 Minor

Fix Foundry ignore path prefix to match the actual workspace directory.

Lines 43-46 use oracle-prototype/..., but this PR’s Foundry project lives under oracle_backend_prototype/..., so these rules won’t apply.

Suggested fix
-# oracle prototype (foundry)
-oracle-prototype/cache/
-oracle-prototype/out/
-oracle-prototype/broadcast/
-oracle-prototype/lib/~
+# oracle backend prototype (foundry)
+oracle_backend_prototype/cache/
+oracle_backend_prototype/out/
+oracle_backend_prototype/broadcast/
+oracle_backend_prototype/lib/
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.gitignore around lines 42 - 46, The .gitignore entries use the wrong
Foundry workspace prefix (oracle-prototype/); update the ignore patterns
oracle-prototype/cache/, oracle-prototype/out/, oracle-prototype/broadcast/, and
oracle-prototype/lib/~ to use the actual workspace directory name
oracle_backend_prototype/ (i.e., oracle_backend_prototype/cache/,
oracle_backend_prototype/out/, oracle_backend_prototype/broadcast/,
oracle_backend_prototype/lib/~) so the ignore rules apply to the current Foundry
project.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In @.gitignore:
- Around line 42-46: The .gitignore entries use the wrong Foundry workspace
prefix (oracle-prototype/); update the ignore patterns oracle-prototype/cache/,
oracle-prototype/out/, oracle-prototype/broadcast/, and oracle-prototype/lib/~
to use the actual workspace directory name oracle_backend_prototype/ (i.e.,
oracle_backend_prototype/cache/, oracle_backend_prototype/out/,
oracle_backend_prototype/broadcast/, oracle_backend_prototype/lib/~) so the
ignore rules apply to the current Foundry project.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: b1f08813-9573-474a-aed4-a716897ecd34

📥 Commits

Reviewing files that changed from the base of the PR and between be7fb23 and 639ee7c.

📒 Files selected for processing (1)
  • .gitignore

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.gitignore.save:
- Line 5: The .gitignore rules are malformed: a path and comment were
concatenated and a backup-file pattern references the wrong directory name; fix
by separating the comment from the path and use the correct directory name and
patterns for backup files and directories (e.g., change the concatenated
"oracle_backend_prototype/lib/# ..." entry into a standalone ignore entry
"oracle_backend_prototype/lib/" with the comment on its own line, and replace
the incorrect "oracle-prototype/lib/~" rule with the correct backup-file pattern
for the actual directory, e.g., "oracle_backend_prototype/lib/*~" or
"oracle_backend_prototype/lib/**~" so Foundry artifact files and editor backups
are reliably ignored).
- Around line 1-50: Remove the backup file .gitignore.save from the commit and
repository (it’s a duplicate of root ignore rules and can drift from
.gitignore); ensure the canonical .gitignore contains any needed entries, update
or re-add any missing patterns there, and re-run your commit without
.gitignore.save (or git rm it) unless this file is intentionally consumed by
tooling and then document that usage.
🪄 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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: fbcde4d5-1e62-4f3b-98fb-2e5b33170f47

📥 Commits

Reviewing files that changed from the base of the PR and between 639ee7c and 51137da.

📒 Files selected for processing (2)
  • .gitignore
  • .gitignore.save

Comment thread .gitignore.save Outdated
Comment on lines +1 to +50
# oracle backend prototype
oracle_backend_prototype/cache/
oracle_backend_prototype/out/
oracle_backend_prototype/broadcast/
oracle_backend_prototype/lib/# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/versions

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*

# env files (can opt-in for committing if needed)
.env*

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts
# oracle prototype (foundry)
oracle-prototype/cache/
oracle-prototype/out/
oracle-prototype/broadcast/
oracle-prototype/lib/~
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.

🧹 Nitpick | 🔵 Trivial

Avoid committing .gitignore.save backup files.

This looks like a backup copy of root ignore rules and introduces drift risk versus .gitignore. Prefer deleting it from the repository unless it is intentionally consumed by tooling.

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

In @.gitignore.save around lines 1 - 50, Remove the backup file .gitignore.save
from the commit and repository (it’s a duplicate of root ignore rules and can
drift from .gitignore); ensure the canonical .gitignore contains any needed
entries, update or re-add any missing patterns there, and re-run your commit
without .gitignore.save (or git rm it) unless this file is intentionally
consumed by tooling and then document that usage.

Comment thread .gitignore.save Outdated
oracle_backend_prototype/cache/
oracle_backend_prototype/out/
oracle_backend_prototype/broadcast/
oracle_backend_prototype/lib/# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
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 | 🟠 Major

Fix malformed ignore patterns that currently won’t match intended paths.

Line 5 concatenates a path and a comment, and Line 50 uses oracle-prototype/lib/~ (backup-file pattern) instead of the directory path. These rules will not reliably ignore Foundry artifacts.

Proposed fix
-oracle_backend_prototype/lib/# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+oracle_backend_prototype/lib/
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
...
-oracle-prototype/lib/~
+oracle-prototype/lib/

Also applies to: 50-50

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

In @.gitignore.save at line 5, The .gitignore rules are malformed: a path and
comment were concatenated and a backup-file pattern references the wrong
directory name; fix by separating the comment from the path and use the correct
directory name and patterns for backup files and directories (e.g., change the
concatenated "oracle_backend_prototype/lib/# ..." entry into a standalone ignore
entry "oracle_backend_prototype/lib/" with the comment on its own line, and
replace the incorrect "oracle-prototype/lib/~" rule with the correct backup-file
pattern for the actual directory, e.g., "oracle_backend_prototype/lib/*~" or
"oracle_backend_prototype/lib/**~" so Foundry artifact files and editor backups
are reliably ignored).

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