Files
smom-dbis-138/test/bridge/trustless/integration/BridgeReserveCoordinator.t.sol
2026-03-02 12:14:09 -08:00

180 lines
7.1 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import {Test, console} from "forge-std/Test.sol";
import "../../../../contracts/bridge/trustless/integration/BridgeReserveCoordinator.sol";
import "../../../../contracts/bridge/trustless/BridgeSwapCoordinator.sol";
import "../../../../contracts/bridge/trustless/InboxETH.sol";
import "../../../../contracts/bridge/trustless/LiquidityPoolETH.sol";
import "../../../../contracts/bridge/trustless/ChallengeManager.sol";
import "../../../../contracts/bridge/trustless/BondManager.sol";
import "../../../../contracts/reserve/ReserveSystem.sol";
import "../../../../contracts/bridge/trustless/integration/StablecoinPegManager.sol";
import "../../../../contracts/bridge/trustless/integration/CommodityPegManager.sol";
import "../../../../contracts/bridge/trustless/integration/ISOCurrencyManager.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.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);
}
function mint(address to, uint256 amount) external {
_mint(to, amount);
}
}
contract BridgeReserveCoordinatorTest is Test {
BridgeReserveCoordinator public coordinator;
BridgeSwapCoordinator public bridgeSwapCoordinator;
ReserveSystem public reserveSystem;
StablecoinPegManager public stablecoinPegManager;
CommodityPegManager public commodityPegManager;
ISOCurrencyManager public isoCurrencyManager;
// Existing bridge contracts
InboxETH public inbox;
LiquidityPoolETH public liquidityPool;
ChallengeManager public challengeManager;
BondManager public bondManager;
// Mock tokens
MockERC20 public usdt;
MockERC20 public usdc;
MockERC20 public weth;
MockERC20 public xau;
address public deployer = address(0xDE0001);
address public user = address(0x1111);
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");
xau = new MockERC20("Gold", "XAU");
// Deploy ReserveSystem
reserveSystem = new ReserveSystem(deployer);
// Register assets in ReserveSystem (using grantRole for PRICE_FEED_ROLE)
vm.stopPrank();
vm.prank(deployer);
reserveSystem.grantRole(keccak256("PRICE_FEED_ROLE"), address(this));
vm.startPrank(address(this));
// Set supported assets and prices
// Note: ReserveSystem doesn't have addSupportedAsset, we'll use updatePriceFeed directly
// which implicitly supports the asset
// Set prices in ReserveSystem (mock)
// Note: updatePriceFeed requires PRICE_FEED_ROLE
vm.stopPrank();
vm.startPrank(deployer);
reserveSystem.grantRole(keccak256("PRICE_FEED_ROLE"), deployer);
reserveSystem.updatePriceFeed(address(usdt), 1e18, block.timestamp); // $1.00
reserveSystem.updatePriceFeed(address(usdc), 1e18, block.timestamp); // $1.00
reserveSystem.updatePriceFeed(address(weth), 1e18, block.timestamp); // 1:1 with ETH
reserveSystem.updatePriceFeed(address(xau), 2000e18, block.timestamp); // $2000/oz
// Deploy StablecoinPegManager
stablecoinPegManager = new StablecoinPegManager(address(reserveSystem));
stablecoinPegManager.registerUSDStablecoin(address(usdt));
stablecoinPegManager.registerUSDStablecoin(address(usdc));
stablecoinPegManager.registerWETH(address(weth));
// Deploy CommodityPegManager
commodityPegManager = new CommodityPegManager(address(reserveSystem));
commodityPegManager.setXAUAddress(address(xau));
commodityPegManager.registerCommodity(address(xau), "XAU", 1e18); // 1:1 with itself
// Deploy ISOCurrencyManager
isoCurrencyManager = new ISOCurrencyManager(address(reserveSystem));
isoCurrencyManager.setXAUAddress(address(xau));
isoCurrencyManager.registerCurrency("USD", address(usdt), 2000e18); // 1 oz XAU = 2000 USD
isoCurrencyManager.registerCurrency("EUR", address(0), 1800e18); // 1 oz XAU = 1800 EUR
// Deploy existing bridge contracts (simplified setup)
bondManager = new BondManager(11000, 1 ether);
challengeManager = new ChallengeManager(address(bondManager), 30 minutes);
liquidityPool = new LiquidityPoolETH(address(weth), 5, 11000);
inbox = new InboxETH(address(bondManager), address(challengeManager), address(liquidityPool));
// Create a mock SwapRouter address (we won't actually use it in these tests)
address mockSwapRouter = address(0x1234567890123456789012345678901234567890);
bridgeSwapCoordinator = new BridgeSwapCoordinator(
address(inbox),
address(liquidityPool),
mockSwapRouter,
address(challengeManager)
);
// Deploy BridgeReserveCoordinator
coordinator = new BridgeReserveCoordinator(
address(bridgeSwapCoordinator),
address(reserveSystem),
address(stablecoinPegManager),
address(commodityPegManager),
address(isoCurrencyManager)
);
// Deposit reserves
usdt.approve(address(reserveSystem), 100000 ether);
reserveSystem.depositReserve(address(usdt), 100000 ether);
vm.stopPrank();
}
function testVerifyReserveStatus() public {
uint256 bridgeAmount = 1000 ether;
BridgeReserveCoordinator.ReserveStatus memory status = coordinator.getReserveStatus(
address(usdt),
bridgeAmount
);
assertEq(status.asset, address(usdt));
assertEq(status.bridgeAmount, bridgeAmount);
assertGt(status.reserveBalance, 0);
assertTrue(status.isSufficient);
}
function testVerifyPegStatus() public {
BridgeReserveCoordinator.PegStatus[] memory pegStatuses = coordinator.verifyPegStatus();
assertGt(pegStatuses.length, 0);
// Check that we have stablecoin peg statuses
bool foundUSDT = false;
for (uint256 i = 0; i < pegStatuses.length; i++) {
if (pegStatuses[i].asset == address(usdt)) {
foundUSDT = true;
assertEq(pegStatuses[i].targetPrice, 1e18); // $1.00
break;
}
}
assertTrue(foundUSDT);
}
function testSetReserveThreshold() public {
uint256 newThreshold = 11000; // 110%
vm.prank(deployer);
coordinator.setReserveThreshold(newThreshold);
assertEq(coordinator.reserveVerificationThresholdBps(), newThreshold);
}
function testRevertInvalidReserveThreshold() public {
uint256 invalidThreshold = 20000; // 200% > max 150%
vm.prank(deployer);
vm.expectRevert(BridgeReserveCoordinator.InvalidReserveThreshold.selector);
coordinator.setReserveThreshold(invalidThreshold);
}
}