Files
smom-dbis-138/test/e2e/NetworkResilience.t.sol
defiQUG 1fb7266469 Add Oracle Aggregator and CCIP Integration
- Introduced Aggregator.sol for Chainlink-compatible oracle functionality, including round-based updates and access control.
- Added OracleWithCCIP.sol to extend Aggregator with CCIP cross-chain messaging capabilities.
- Created .gitmodules to include OpenZeppelin contracts as a submodule.
- Developed a comprehensive deployment guide in NEXT_STEPS_COMPLETE_GUIDE.md for Phase 2 and smart contract deployment.
- Implemented Vite configuration for the orchestration portal, supporting both Vue and React frameworks.
- Added server-side logic for the Multi-Cloud Orchestration Portal, including API endpoints for environment management and monitoring.
- Created scripts for resource import and usage validation across non-US regions.
- Added tests for CCIP error handling and integration to ensure robust functionality.
- Included various new files and directories for the orchestration portal and deployment scripts.
2025-12-12 14:57:48 -08:00

141 lines
4.8 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import {Test, console} from "forge-std/Test.sol";
import {Aggregator} from "../../contracts/oracle/Aggregator.sol";
import {CCIPSender} from "../../contracts/ccip/CCIPSender.sol";
contract NetworkResilienceTest is Test {
Aggregator public aggregator;
address public transmitter1;
address public transmitter2;
address public transmitter3;
function setUp() public {
aggregator = new Aggregator("ETH/USD", address(this), 60, 50);
transmitter1 = address(0x111);
transmitter2 = address(0x222);
transmitter3 = address(0x333);
aggregator.addTransmitter(transmitter1);
aggregator.addTransmitter(transmitter2);
aggregator.addTransmitter(transmitter3);
}
function testOracleContinuesWithOneTransmitterFailure() public {
uint256 price1 = 25000000000;
uint256 price2 = 25100000000;
// Transmitter 1 updates
vm.prank(transmitter1);
aggregator.updateAnswer(price1);
// Fast forward past heartbeat to create new round
vm.warp(block.timestamp + 61);
// Transmitter 1 fails, transmitter 2 continues with new round
vm.prank(transmitter2);
aggregator.updateAnswer(price2);
(uint256 roundId, int256 answer, , , ) = aggregator.latestRoundData();
assertEq(uint256(answer), price2, "Oracle should continue with remaining transmitters");
assertGt(roundId, 1, "Should create new round");
}
function testOracleHandlesMultipleTransmitterFailures() public {
uint256 price1 = 25000000000;
uint256 price2 = 25100000000;
uint256 price3 = 25200000000;
// All transmitters update in round 1
vm.prank(transmitter1);
aggregator.updateAnswer(price1);
vm.prank(transmitter2);
aggregator.updateAnswer(price1);
vm.prank(transmitter3);
aggregator.updateAnswer(price1);
// Fast forward past heartbeat to create new round
vm.warp(block.timestamp + 61);
// Two transmitters fail, one continues with new round
vm.prank(transmitter3);
aggregator.updateAnswer(price3);
(uint256 roundId, int256 answer, , , ) = aggregator.latestRoundData();
assertEq(uint256(answer), price3, "Oracle should continue with remaining transmitter");
assertGt(roundId, 1, "Should create new round");
}
function testOracleRecoversFromPause() public {
uint256 price1 = 25000000000;
uint256 price2 = 25100000000;
// Update before pause
vm.prank(transmitter1);
aggregator.updateAnswer(price1);
// Verify initial state
(uint256 roundId1, int256 answer1, , , ) = aggregator.latestRoundData();
assertEq(uint256(answer1), price1, "Initial price should be set");
// Pause oracle (must be called by admin)
aggregator.pause();
// Try to update (should fail)
vm.prank(transmitter1);
vm.expectRevert("Aggregator: paused");
aggregator.updateAnswer(price2);
// Unpause (must be called by admin)
aggregator.unpause();
// Update should work again
vm.prank(transmitter1);
aggregator.updateAnswer(price2);
(uint256 roundId2, int256 answer2, , , ) = aggregator.latestRoundData();
assertEq(uint256(answer2), price2, "Oracle should recover after unpause");
assertGt(roundId2, roundId1, "Should create new round after unpause");
}
function testOracleHandlesStaleData() public {
uint256 price1 = 25000000000;
// Initial update
vm.prank(transmitter1);
aggregator.updateAnswer(price1);
// Fast forward past heartbeat
vm.warp(block.timestamp + 61);
// New update should create new round
vm.prank(transmitter1);
aggregator.updateAnswer(price1);
(uint256 roundId, , , , ) = aggregator.latestRoundData();
assertGt(roundId, 1, "Should create new round after heartbeat");
}
function testOracleHandlesPriceDeviation() public {
uint256 price1 = 25000000000; // $250.00
uint256 price2 = 25125000000; // $251.25 (0.5% deviation)
// Initial update
vm.prank(transmitter1);
aggregator.updateAnswer(price1);
// Update with deviation
vm.prank(transmitter1);
aggregator.updateAnswer(price2);
(uint256 roundId, int256 answer, , , ) = aggregator.latestRoundData();
assertEq(uint256(answer), price2, "Oracle should accept price deviation");
assertGt(roundId, 1, "Should create new round on deviation");
}
}