Files
smom-dbis-138/test/iso4217w/ReserveOracle.t.sol
2026-03-02 12:14:09 -08:00

125 lines
4.3 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "forge-std/Test.sol";
import "../../contracts/iso4217w/oracle/ReserveOracle.sol";
contract ReserveOracleTest is Test {
ReserveOracle public oracle;
address public admin = address(0x1);
address public oracle1 = address(0x2);
address public oracle2 = address(0x3);
address public oracle3 = address(0x4);
string public constant CURRENCY_CODE = "USD";
uint256 public constant STALENESS_THRESHOLD = 3600; // 1 hour
uint256 public constant QUORUM_SIZE = 3;
function setUp() public {
vm.warp(STALENESS_THRESHOLD + 1); // Avoid underflow: block.timestamp - stalenessThreshold
vm.startPrank(admin);
oracle = new ReserveOracle(admin, QUORUM_SIZE, STALENESS_THRESHOLD);
// Add oracles (also grants ORACLE_ROLE)
oracle.addOracle(oracle1);
oracle.addOracle(oracle2);
oracle.addOracle(oracle3);
vm.stopPrank();
}
function test_SubmitReserveReport() public {
uint256 reserve = 10000e2;
bytes32 attestationHash = keccak256("attestation");
// Submit from all 3 oracles to reach quorum (QUORUM_SIZE=3)
vm.prank(oracle1);
oracle.submitReserveReport(CURRENCY_CODE, reserve, attestationHash);
vm.prank(oracle2);
oracle.submitReserveReport(CURRENCY_CODE, reserve, attestationHash);
vm.prank(oracle3);
oracle.submitReserveReport(CURRENCY_CODE, reserve, attestationHash);
(uint256 verifiedReserve, uint256 timestamp) = oracle.getVerifiedReserve(CURRENCY_CODE);
assertEq(verifiedReserve, reserve);
assertGt(timestamp, 0);
}
function test_GetVerifiedReserve_Quorum() public {
// Submit reports from all 3 oracles
uint256 reserve = 10000e2;
bytes32 attestationHash = keccak256("attestation");
vm.prank(oracle1);
oracle.submitReserveReport(CURRENCY_CODE, reserve, attestationHash);
vm.prank(oracle2);
oracle.submitReserveReport(CURRENCY_CODE, reserve, attestationHash);
vm.prank(oracle3);
oracle.submitReserveReport(CURRENCY_CODE, reserve, attestationHash);
(uint256 verifiedReserve, ) = oracle.getVerifiedReserve(CURRENCY_CODE);
// Should get consensus (all same)
assertEq(verifiedReserve, reserve);
}
function test_IsQuorumMet() public {
uint256 reserve = 10000e2;
bytes32 attestationHash = keccak256("attestation");
// Submit from 2 oracles (not quorum yet)
vm.prank(oracle1);
oracle.submitReserveReport(CURRENCY_CODE, reserve, attestationHash);
vm.prank(oracle2);
oracle.submitReserveReport(CURRENCY_CODE, reserve, attestationHash);
(bool quorum1, ) = oracle.isQuorumMet(CURRENCY_CODE);
assertFalse(quorum1, "Should not have quorum with 2/3");
// Submit from third oracle
vm.prank(oracle3);
oracle.submitReserveReport(CURRENCY_CODE, reserve, attestationHash);
(bool quorum2, ) = oracle.isQuorumMet(CURRENCY_CODE);
assertTrue(quorum2, "Should have quorum with 3/3");
}
function test_RemoveStaleReports() public {
uint256 reserve = 10000e2;
bytes32 attestationHash = keccak256("attestation");
vm.prank(oracle1);
oracle.submitReserveReport(CURRENCY_CODE, reserve, attestationHash);
// Fast forward time to make reports stale
vm.warp(block.timestamp + STALENESS_THRESHOLD + 1);
// Stale reports should not count towards quorum
(bool quorum, ) = oracle.isQuorumMet(CURRENCY_CODE);
assertFalse(quorum, "Stale reports should not count");
}
function test_GetConsensusReserve() public {
bytes32 attestationHash = keccak256("attestation");
// Submit different reports
vm.prank(oracle1);
oracle.submitReserveReport(CURRENCY_CODE, 10000e2, attestationHash);
vm.prank(oracle2);
oracle.submitReserveReport(CURRENCY_CODE, 10001e2, attestationHash); // 1 USD difference
vm.prank(oracle3);
oracle.submitReserveReport(CURRENCY_CODE, 9999e2, attestationHash); // 1 USD difference
// Consensus should be median or average
uint256 consensus = oracle.getConsensusReserve(CURRENCY_CODE);
assertGt(consensus, 0, "Should have consensus value");
}
}