// SPDX-License-Identifier: MIT pragma solidity ^0.8.19; import {Test, console} from "forge-std/Test.sol"; import "../../../../contracts/bridge/trustless/integration/StablecoinPegManager.sol"; import "../../../../contracts/reserve/ReserveSystem.sol"; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; contract MockERC20 is ERC20 { constructor(string memory name, string memory symbol) ERC20(name, symbol) { _mint(msg.sender, 1000000 ether); } } contract StablecoinPegManagerTest is Test { StablecoinPegManager public pegManager; ReserveSystem public reserveSystem; MockERC20 public usdt; MockERC20 public usdc; MockERC20 public weth; address public deployer = address(0xDE0001); function setUp() public { vm.startPrank(deployer); // Deploy mock tokens usdt = new MockERC20("Tether USD", "USDT"); usdc = new MockERC20("USD Coin", "USDC"); weth = new MockERC20("Wrapped Ether", "WETH"); // Deploy ReserveSystem reserveSystem = new ReserveSystem(deployer); // Grant PRICE_FEED_ROLE to this test contract so we can update prices reserveSystem.grantRole(keccak256("PRICE_FEED_ROLE"), address(this)); // Deploy StablecoinPegManager pegManager = new StablecoinPegManager(address(reserveSystem)); // Register assets pegManager.registerUSDStablecoin(address(usdt)); pegManager.registerUSDStablecoin(address(usdc)); pegManager.registerWETH(address(weth)); vm.stopPrank(); } function testRegisterUSDStablecoin() public { address[] memory assets = pegManager.getSupportedAssets(); assertEq(assets.length, 3); // USDT, USDC, WETH } function testCheckUSDpeg() public { // Set price at $1.00 (on peg) reserveSystem.updatePriceFeed(address(usdt), 1e18, block.timestamp); (bool isMaintained, int256 deviationBps) = pegManager.checkUSDpeg(address(usdt)); assertTrue(isMaintained); assertEq(deviationBps, 0); } function testCheckUSDpegDeviation() public { // Set price at $1.01 (1% above peg) reserveSystem.updatePriceFeed(address(usdt), 1.01e18, block.timestamp); (bool isMaintained, int256 deviationBps) = pegManager.checkUSDpeg(address(usdt)); // Deviation should be 100 bps (1%), threshold is 50 bps (0.5%) assertFalse(isMaintained); assertEq(deviationBps, 100); } function testCheckETHpeg() public { // Set price at 1:1 (on peg) reserveSystem.updatePriceFeed(address(weth), 1e18, block.timestamp); (bool isMaintained, int256 deviationBps) = pegManager.checkETHpeg(address(weth)); assertTrue(isMaintained); assertEq(deviationBps, 0); } function testCalculateDeviation() public { int256 deviation = pegManager.calculateDeviation(address(usdt), 1.01e18, 1e18); assertEq(deviation, 100); // 1% = 100 bps } function testGetPegStatus() public { reserveSystem.updatePriceFeed(address(usdt), 1e18, block.timestamp); (uint256 currentPrice, uint256 targetPrice, int256 deviationBps, bool isMaintained) = pegManager.getPegStatus(address(usdt)); assertEq(currentPrice, 1e18); assertEq(targetPrice, 1e18); assertEq(deviationBps, 0); assertTrue(isMaintained); } function testSetUSDPegThreshold() public { uint256 newThreshold = 100; // 1% vm.prank(deployer); pegManager.setUSDPegThreshold(newThreshold); assertEq(pegManager.usdPegThresholdBps(), newThreshold); } }