1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^ 0.8.20 ;
3
+
4
+ import "forge-std/Test.sol " ;
5
+ import "openzeppelin/proxy/transparent/TransparentUpgradeableProxy.sol " ;
6
+ import {ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol " ;
7
+ import {FXToken} from "../../src/fx/FXToken.sol " ;
8
+
9
+ contract FXTokenTest is Test {
10
+ FXToken token;
11
+
12
+ address admin = address (0x1 );
13
+ address minter = address (0x2 );
14
+ address blocker = address (0x2 );
15
+ address alice = address (0xa );
16
+ address bob = address (0xb );
17
+ address charlie = address (0xc );
18
+
19
+ function setUp () public {
20
+ // admin deploys, so becomes admin
21
+ vm.startPrank (admin);
22
+ FXToken fxTokenImplementation = new FXToken ();
23
+
24
+ TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy (
25
+ address (fxTokenImplementation),
26
+ address (alice),
27
+ abi.encodeWithSelector (fxTokenImplementation.initialize.selector , "fx USDC " , "fxUSDC " , 6 )
28
+ );
29
+ token = FXToken (address (proxy));
30
+
31
+ // Set roles
32
+ token.grantRole (token.MINTER_ROLE (), minter);
33
+ token.grantRole (token.BLOCK_MANAGER_ROLE (), blocker);
34
+
35
+ vm.stopPrank ();
36
+ }
37
+
38
+ function testInitialSetup () public view {
39
+ assertEq (token.name (), "fx USDC " );
40
+ assertEq (token.symbol (), "fxUSDC " );
41
+ assertEq (token.decimals (), 6 );
42
+ assertTrue (token.hasRole (token.MINTER_ROLE (), minter));
43
+ assertTrue (token.hasRole (token.BLOCK_MANAGER_ROLE (), blocker));
44
+ }
45
+
46
+ function testMint () public {
47
+ vm.prank (minter);
48
+ token.mint (alice, 100 );
49
+
50
+ assertEq (token.balanceOf (alice), 100 );
51
+ }
52
+
53
+ function testBurn () public {
54
+ vm.prank (minter);
55
+ token.mint (alice, 100 );
56
+
57
+ assertEq (token.balanceOf (alice), 100 );
58
+
59
+ vm.prank (minter);
60
+ token.burn (alice, 50 );
61
+
62
+ assertEq (token.balanceOf (alice), 50 );
63
+ }
64
+
65
+ function testBlockUser () public {
66
+ vm.prank (minter);
67
+ token.mint (bob, 100 );
68
+
69
+ vm.prank (blocker);
70
+ token.setBlocked (bob, true );
71
+
72
+ assertTrue (token.isBlocked (bob));
73
+
74
+ // Minting to a blocked user should revert
75
+ vm.prank (minter);
76
+ vm.expectRevert ("FxToken: recipient is blocked " );
77
+ token.mint (bob, 100 );
78
+
79
+ // Burning from a blocked user is allowed
80
+ vm.prank (minter);
81
+ token.burn (bob, 50 );
82
+
83
+ assertEq (token.balanceOf (bob), 50 );
84
+
85
+ vm.prank (minter);
86
+ token.mint (alice, 100 );
87
+
88
+ assertEq (token.balanceOf (alice), 100 );
89
+
90
+ vm.prank (alice);
91
+ vm.expectRevert ("FxToken: recipient is blocked " );
92
+ token.transfer (bob, 50 );
93
+
94
+ // A blocked user cannot transfer tokens
95
+ vm.prank (bob);
96
+ vm.expectRevert ("FxToken: sender is blocked " );
97
+ token.transfer (alice, 50 );
98
+
99
+ // A blocked user approving is allowed, but the spender cannot transfer
100
+ vm.prank (bob);
101
+ token.approve (alice, 50 );
102
+
103
+ vm.prank (alice);
104
+ vm.expectRevert ("FxToken: sender is blocked " );
105
+ token.transferFrom (bob, alice, 50 );
106
+
107
+ // Cannot transferFrom to a blocked user
108
+ vm.prank (alice);
109
+ token.approve (charlie, 50 );
110
+
111
+ vm.prank (charlie);
112
+ vm.expectRevert ("FxToken: recipient is blocked " );
113
+ token.transferFrom (alice, bob, 50 );
114
+
115
+ // Cannot spend allowance if spender is blocked
116
+ vm.prank (alice);
117
+ token.approve (bob, 50 );
118
+
119
+ vm.prank (bob);
120
+ vm.expectRevert ("FxToken: spender is blocked " );
121
+ token.transferFrom (alice, charlie, 50 );
122
+ }
123
+
124
+ function testCannotBlockZeroAddress () public {
125
+ vm.prank (blocker);
126
+ vm.expectRevert ("FxToken: cannot block zero address " );
127
+ token.setBlocked (address (0 ), true );
128
+ }
129
+
130
+
131
+
132
+ }
0 commit comments