From c92bcd8a2e748f5c22b416b8f8024f5fc25eacc1 Mon Sep 17 00:00:00 2001 From: zacksfF Date: Mon, 3 Nov 2025 12:20:17 +0100 Subject: [PATCH 1/2] release --- test/unit/.main | 1 + test/unit/PriceOracleTest.t.sol | 63 +++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 test/unit/.main diff --git a/test/unit/.main b/test/unit/.main new file mode 100644 index 0000000..30b81db --- /dev/null +++ b/test/unit/.main @@ -0,0 +1 @@ +release \ No newline at end of file diff --git a/test/unit/PriceOracleTest.t.sol b/test/unit/PriceOracleTest.t.sol index e69de29..fa003cb 100644 --- a/test/unit/PriceOracleTest.t.sol +++ b/test/unit/PriceOracleTest.t.sol @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import "forge-std/Test.sol"; +import {PriceOracle} from "src/libraries/PriceOracle.sol"; +import {VaultMath} from "src/libraries/VaultMath.sol"; +import {MockPriceFeed} from "src/mocks/MockPriceFeed.sol"; +import "lib/chainlink-brownie-contracts/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol"; + +contract PriceOracleTest is Test { + function testGetLatestPrice_returnsScaledPrice() public { + // keep block.number and block.timestamp aligned so both staleness checks pass + vm.roll(100); + vm.warp(100); + + MockPriceFeed mock = new MockPriceFeed(8, int256(2000e8)); + + uint256 price = PriceOracle.getLatestPrice(AggregatorV3Interface(address(mock))); + + uint256 expected = uint256(2000e8) * VaultMath.ADDITIONAL_FEED_PRECISION; + assertEq(price, expected); + } + + function testRevertsOnInvalidPriceZero() public { + vm.roll(1); + vm.warp(1); + MockPriceFeed mock = new MockPriceFeed(8, int256(1e8)); + // set the latest answer to zero + mock.updateAnswer(0); + + vm.expectRevert(bytes("Invalid price")); + PriceOracle.getLatestPrice(AggregatorV3Interface(address(mock))); + } + + function testRevertsOnStaleTime() public { + // normal block/ts + vm.roll(1); + vm.warp(100000); + + MockPriceFeed mock = new MockPriceFeed(8, int256(2000e8)); + + // set the round's updatedAt to older than timeout (3 hours) + uint256 old = block.timestamp - (3 hours + 1); + // use a new round id + mock.updateRoundData(2, int256(2000e8), old, old); + + vm.expectRevert(bytes("Price too stale (time)")); + PriceOracle.getLatestPrice(AggregatorV3Interface(address(mock))); + } + + function testRevertsOnStaleBlocks() public { + // Make block.number large while keeping timestamp small so block-based check fails + vm.roll(10000); + vm.warp(1000); + + MockPriceFeed mock = new MockPriceFeed(8, int256(2000e8)); + + // time-based check passes (updatedAt == block.timestamp), but block check should fail + vm.expectRevert(bytes("Price too stale (blocks)")); + PriceOracle.getLatestPrice(AggregatorV3Interface(address(mock))); + } +} + From cbcfb508fc42acc544dad1e74c65dd14e2b49921 Mon Sep 17 00:00:00 2001 From: zacksfF Date: Mon, 3 Nov 2025 12:27:44 +0100 Subject: [PATCH 2/2] feat: unit test for priceOracle #3 --- test/unit/PriceOracleTest.t.sol | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/unit/PriceOracleTest.t.sol b/test/unit/PriceOracleTest.t.sol index fa003cb..a239d7e 100644 --- a/test/unit/PriceOracleTest.t.sol +++ b/test/unit/PriceOracleTest.t.sol @@ -7,6 +7,9 @@ import {VaultMath} from "src/libraries/VaultMath.sol"; import {MockPriceFeed} from "src/mocks/MockPriceFeed.sol"; import "lib/chainlink-brownie-contracts/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol"; +/// @title PriceOracleTest +/// @notice Unit tests for the PriceOracle library + contract PriceOracleTest is Test { function testGetLatestPrice_returnsScaledPrice() public { // keep block.number and block.timestamp aligned so both staleness checks pass @@ -25,7 +28,7 @@ contract PriceOracleTest is Test { vm.roll(1); vm.warp(1); MockPriceFeed mock = new MockPriceFeed(8, int256(1e8)); - // set the latest answer to zero + // set the latest answer to zero mock.updateAnswer(0); vm.expectRevert(bytes("Invalid price"));