Skip to content

Commit 5b191e9

Browse files
committed
added tests
1 parent 521d85c commit 5b191e9

File tree

3 files changed

+136
-4
lines changed

3 files changed

+136
-4
lines changed

scripts/deploy-fxUSDC.s.sol

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import {TokenizedSubAccount} from "../src/tokenizedSubaccounts/TSA.sol";
2222
import "openzeppelin/proxy/transparent/ProxyAdmin.sol";
2323
import {TSAShareHandler} from "../src/tokenizedSubaccounts/TSAShareHandler.sol";
2424
import {Vm} from "forge-std/Vm.sol";
25-
import {FxToken} from "../src/FX/FXToken.sol";
25+
import {FXToken} from "../src/fx/FXToken.sol";
2626
import {WrappedERC20Asset} from "v2-core/src/assets/WrappedERC20Asset.sol";
2727

2828

@@ -37,7 +37,7 @@ contract DeployFXUSDC is Utils {
3737
address deployer = vm.addr(deployerPrivateKey);
3838
console2.log("deployer: ", deployer);
3939

40-
FxToken fxTokenImplementation = new FxToken();
40+
FXToken fxTokenImplementation = new FXToken();
4141

4242
TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
4343
address(fxTokenImplementation),
@@ -46,7 +46,7 @@ contract DeployFXUSDC is Utils {
4646
);
4747

4848

49-
FxToken fxUSDC = FxToken(address(proxy));
49+
FXToken fxUSDC = FXToken(address(proxy));
5050

5151
console2.log("fxUSDC: ", address(fxUSDC));
5252
console2.log("fxUSDCImp: ", address(fxTokenImplementation));

src/FX/FXToken.sol renamed to src/fx/FXToken.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import {AccessControlUpgradeable} from "openzeppelin-upgradeable/access/AccessCo
44
import {ERC20Upgradeable, Initializable} from "openzeppelin-upgradeable/token/ERC20/ERC20Upgradeable.sol";
55

66

7-
contract FxToken is Initializable, ERC20Upgradeable, AccessControlUpgradeable {
7+
contract FXToken is Initializable, ERC20Upgradeable, AccessControlUpgradeable {
88
bytes32 public constant MINTER_ROLE = keccak256("MINTER");
99
bytes32 public constant BLOCK_MANAGER_ROLE = keccak256("BLOCK_MANAGER");
1010
// keccak256(abi.encode(uint256(keccak256("FxToken")) - 1)) & ~bytes32(uint256(0xff))

test/fx/FXToken.sol

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
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

Comments
 (0)