// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "forge-std/Test.sol"; import "../src/Compliance.sol"; import "../src/interfaces/ICoupon.sol"; contract ComplianceTest is Test { Compliance compliance; address admin = address(1); address user1 = address(2); address user2 = address(3); address officer = address(4); function setUp() public { vm.startPrank(admin); compliance = new Compliance(); compliance.initialize(admin); compliance.grantRole(keccak256("COMPLIANCE_OFFICER_ROLE"), officer); vm.stopPrank(); } // === OFAC === function test_AddToBlacklist() public { vm.prank(officer); compliance.addToBlacklist(user1, "OFAC SDN"); assertTrue(compliance.isBlacklisted(user1)); } function test_RemoveFromBlacklist() public { vm.prank(officer); compliance.addToBlacklist(user1, "OFAC SDN"); vm.prank(admin); compliance.removeFromBlacklist(user1); assertFalse(compliance.isBlacklisted(user1)); } function test_RemoveFromBlacklistOnlyGovernance() public { vm.prank(officer); compliance.addToBlacklist(user1, "OFAC SDN"); vm.prank(officer); vm.expectRevert(); compliance.removeFromBlacklist(user1); } // === KYC === function test_SetKycLevel() public { vm.prank(admin); compliance.setKycLevel(user1, 2); assertEq(compliance.getKycLevel(user1), 2); } function test_InvalidKycLevelReverts() public { vm.prank(admin); vm.expectRevert("Compliance: invalid KYC level"); compliance.setKycLevel(user1, 4); } function test_RequireKycLevelSuccess() public view { // L0 默认 compliance.requireKycLevel(user1, 0); } function test_RequireKycLevelFails() public { vm.expectRevert("Compliance: insufficient KYC level"); compliance.requireKycLevel(user1, 1); } function test_BatchSetKycLevel() public { address[] memory accounts = new address[](2); accounts[0] = user1; accounts[1] = user2; uint8[] memory levels = new uint8[](2); levels[0] = 1; levels[1] = 2; vm.prank(admin); compliance.batchSetKycLevel(accounts, levels); assertEq(compliance.getKycLevel(user1), 1); assertEq(compliance.getKycLevel(user2), 2); } // === Freeze === function test_FreezeAccount() public { vm.prank(admin); compliance.freezeAccount(user1); assertTrue(compliance.isFrozen(user1)); } function test_UnfreezeAccount() public { vm.prank(admin); compliance.freezeAccount(user1); vm.prank(admin); compliance.unfreezeAccount(user1); assertFalse(compliance.isFrozen(user1)); } // === Travel Rule === function test_RecordTravelRule() public { vm.prank(officer); compliance.recordTravelRule(user1, user2, keccak256("sender"), keccak256("receiver")); assertTrue(compliance.hasTravelRuleRecord(user1, user2)); } // === Pre-Trade Check === function test_PreTradeCheckUtilityRequiresKycL1() public { // 无 KYC vm.expectRevert("Compliance: buyer needs KYC L1 for Utility"); compliance.preTradeCheck(user1, user2, 100e6, ICoupon.CouponType.Utility); } function test_PreTradeCheckSecurityRequiresKycL2() public { vm.startPrank(admin); compliance.setKycLevel(user1, 1); compliance.setKycLevel(user2, 1); vm.stopPrank(); vm.expectRevert("Compliance: buyer needs KYC L2 for Security"); compliance.preTradeCheck(user1, user2, 100e6, ICoupon.CouponType.Security); } function test_PreTradeCheckLargeTradeRequiresKycL2() public { vm.startPrank(admin); compliance.setKycLevel(user1, 1); compliance.setKycLevel(user2, 1); vm.stopPrank(); vm.expectRevert("Compliance: buyer needs KYC L2 for large trade"); compliance.preTradeCheck(user1, user2, 10000e6, ICoupon.CouponType.Utility); } function test_PreTradeCheckBlacklistedReverts() public { vm.startPrank(admin); compliance.setKycLevel(user1, 2); compliance.setKycLevel(user2, 2); vm.stopPrank(); vm.prank(officer); compliance.addToBlacklist(user1, "OFAC"); vm.expectRevert("Compliance: buyer blacklisted"); compliance.preTradeCheck(user1, user2, 100e6, ICoupon.CouponType.Utility); } function test_PreTradeCheckFrozenReverts() public { vm.startPrank(admin); compliance.setKycLevel(user1, 2); compliance.setKycLevel(user2, 2); compliance.freezeAccount(user2); vm.stopPrank(); vm.expectRevert("Compliance: seller frozen"); compliance.preTradeCheck(user1, user2, 100e6, ICoupon.CouponType.Utility); } // === P2P Check === function test_P2pCheckRequiresTravelRule() public { vm.startPrank(admin); compliance.setKycLevel(user1, 2); compliance.setKycLevel(user2, 2); vm.stopPrank(); vm.expectRevert("Compliance: Travel Rule data required"); compliance.p2pComplianceCheck(user1, user2, 5000e6); } function test_P2pCheckWithTravelRuleSuccess() public { vm.startPrank(admin); compliance.setKycLevel(user1, 2); compliance.setKycLevel(user2, 2); vm.stopPrank(); vm.prank(officer); compliance.recordTravelRule(user1, user2, keccak256("s"), keccak256("r")); // 不应 revert compliance.p2pComplianceCheck(user1, user2, 5000e6); } function test_P2pCheckBelowThresholdNoTravelRule() public { // $2,999 无需 Travel Rule compliance.p2pComplianceCheck(user1, user2, 2999e6); } }