// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "forge-std/Test.sol"; import "../../contracts/iso4217w/controllers/MintController.sol"; import "../../contracts/iso4217w/ISO4217WToken.sol"; import "../../contracts/iso4217w/ComplianceGuard.sol"; import "../../contracts/iso4217w/oracle/ReserveOracle.sol"; import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; contract MintControllerTest is Test { MintController public mintController; ISO4217WToken public token; ComplianceGuard public complianceGuard; ReserveOracle public reserveOracle; address public admin = address(0x1); address public minter = address(0x2); address public user = address(0x3); address public oracle1 = address(0x4); address public custodian = address(0x5); string public constant CURRENCY_CODE = "USD"; string public constant TOKEN_SYMBOL = "USDW"; function setUp() public { vm.warp(3601); // Avoid ReserveOracle underflow (block.timestamp - stalenessThreshold) vm.startPrank(admin); complianceGuard = new ComplianceGuard(admin); reserveOracle = new ReserveOracle(admin, 1, 3600); // quorum=1 for tests, 1 hour staleness // Add oracle to reserve oracle reserveOracle.addOracle(oracle1); mintController = new MintController( admin, address(reserveOracle), address(complianceGuard) ); // Deploy token ISO4217WToken implementation = new ISO4217WToken(); bytes memory initData = abi.encodeWithSelector( ISO4217WToken.initialize.selector, "USDW Token", TOKEN_SYMBOL, CURRENCY_CODE, 2, custodian, address(mintController), address(0x999), // burn controller placeholder address(complianceGuard), admin ); ERC1967Proxy proxy = new ERC1967Proxy(address(implementation), initData); token = ISO4217WToken(address(proxy)); // Grant roles token.grantRole(keccak256("MINTER_ROLE"), address(mintController)); token.grantRole(keccak256("RESERVE_UPDATE_ROLE"), oracle1); // Grant minter role and approve token mintController.grantRole(keccak256("MINTER_ROLE"), minter); mintController.approveToken(address(token)); vm.stopPrank(); } function test_CanMint() public { // Set reserve vm.prank(oracle1); token.updateVerifiedReserve(10000e2); // 10,000 USD reserve // Submit reserve report to oracle vm.prank(oracle1); reserveOracle.submitReserveReport(CURRENCY_CODE, 10000e2, keccak256("attestation")); // Check if can mint (bool canMint, ) = mintController.canMint(address(token), 1000e2); assertTrue(canMint, "Should be able to mint with sufficient reserve"); } function test_CanMint_RevertIfReserveInsufficient() public { // Set reserve below supply vm.prank(oracle1); token.updateVerifiedReserve(500e2); // 500 USD reserve vm.prank(oracle1); reserveOracle.submitReserveReport(CURRENCY_CODE, 500e2, keccak256("attestation")); // Try to mint more than reserve allows (bool canMint, ) = mintController.canMint(address(token), 1000e2); assertFalse(canMint, "Should not be able to mint with insufficient reserve"); } function test_Mint() public { // Set reserve vm.prank(oracle1); token.updateVerifiedReserve(10000e2); vm.prank(oracle1); reserveOracle.submitReserveReport(CURRENCY_CODE, 10000e2, keccak256("attestation")); bytes32 settlementId = keccak256("SETTLEMENT_001"); vm.prank(minter); mintController.mint( address(token), user, 1000e2, // 1,000 USDW settlementId ); assertEq(token.balanceOf(user), 1000e2); assertEq(token.totalSupply(), 1000e2); } function test_Mint_RevertIfNotAuthorized() public { address unauthorized = address(0x999); vm.prank(unauthorized); vm.expectRevert(); mintController.mint( address(token), user, 1000e2, keccak256("SETTLEMENT_001") ); } }