gcx/blockchain/genex-contracts/test/ExchangeRateOracle.t.sol

127 lines
3.4 KiB
Solidity
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "forge-std/Test.sol";
import "../src/ExchangeRateOracle.sol";
import "../src/interfaces/IChainlinkPriceFeed.sol";
contract MockPriceFeed is IChainlinkPriceFeed {
int256 private _price;
uint256 private _updatedAt;
uint8 private _decimals;
constructor(int256 price, uint8 dec) {
_price = price;
_updatedAt = block.timestamp;
_decimals = dec;
}
function setPrice(int256 price) external {
_price = price;
_updatedAt = block.timestamp;
}
function setUpdatedAt(uint256 ts) external {
_updatedAt = ts;
}
function latestRoundData()
external
view
override
returns (uint80, int256, uint256, uint256, uint80)
{
return (1, _price, block.timestamp, _updatedAt, 1);
}
function decimals() external view override returns (uint8) {
return _decimals;
}
function description() external pure override returns (string memory) {
return "Mock Price Feed";
}
}
contract ExchangeRateOracleTest is Test {
ExchangeRateOracle oracle;
MockPriceFeed cnyFeed;
MockPriceFeed jpyFeed;
address admin = address(1);
function setUp() public {
vm.startPrank(admin);
oracle = new ExchangeRateOracle();
oracle.initialize(900, admin); // 15 min staleness
cnyFeed = new MockPriceFeed(7_2500_0000, 8); // 7.25 CNY/USD
jpyFeed = new MockPriceFeed(150_0000_0000, 8); // 150 JPY/USD
oracle.setPriceFeed("CNY", address(cnyFeed));
oracle.setPriceFeed("JPY", address(jpyFeed));
vm.stopPrank();
}
function test_GetRateCNY() public view {
uint256 rate = oracle.getRate("CNY");
assertEq(rate, 7_2500_0000);
}
function test_GetRateJPY() public view {
uint256 rate = oracle.getRate("JPY");
assertEq(rate, 150_0000_0000);
}
function test_UnsupportedCurrencyReverts() public {
vm.expectRevert("Oracle: unsupported currency");
oracle.getRate("EUR");
}
function test_StaleDataReverts() public {
// Ensure block.timestamp is large enough to avoid underflow
vm.warp(2000);
// 设置 CNY feed 过期20分钟前更新
cnyFeed.setUpdatedAt(block.timestamp - 1200);
vm.expectRevert("Oracle: stale price data");
oracle.getRate("CNY");
}
function test_GetRateDetails() public view {
(uint256 rate, uint256 updatedAt, uint8 decimals) = oracle.getRateDetails("CNY");
assertEq(rate, 7_2500_0000);
assertGt(updatedAt, 0);
assertEq(decimals, 8);
}
function test_SetMaxStaleness() public {
vm.prank(admin);
oracle.setMaxStaleness(600); // 10 min
assertEq(oracle.maxStaleness(), 600);
}
function test_RemovePriceFeed() public {
vm.prank(admin);
oracle.removePriceFeed("CNY");
vm.expectRevert("Oracle: unsupported currency");
oracle.getRate("CNY");
}
function test_SupportedCurrencyCount() public view {
assertEq(oracle.supportedCurrencyCount(), 2);
}
function test_InvalidPriceReverts() public {
MockPriceFeed badFeed = new MockPriceFeed(0, 8);
vm.prank(admin);
oracle.setPriceFeed("BAD", address(badFeed));
vm.expectRevert("Oracle: invalid price");
oracle.getRate("BAD");
}
}