pragma solidity 0.8.20; import {Test} from "forge-std/Test.sol"; import {Fatso} from "../../src/FatsoERC20.sol"; import {GhostAuthority} from "../../src/GhostAuthority.sol"; import {GhostAccessControlled} from "../../src/types/GhostAccessControlled.sol"; import {ERC20PermitTest} from "./Permit.t.sol"; import {ERC20AllowanceTest} from "./Allowance.t.sol"; import {ERC20TransferTest} from "./Transfer.t.sol"; contract FatsoTest is Test, ERC20PermitTest, ERC20AllowanceTest, ERC20TransferTest { GhostAuthority authority; Fatso token; address constant DEPLOYER = 0x0000000000000000000000000000000000000001; address constant VAULT = 0x0000000000000000000000000000000000000002; address constant ALICE = 0x0000000000000000000000000000000000000003; address constant BOB = 0x0000000000000000000000000000000000000004; uint256 constant AMOUNT = 69; uint256 constant MAX_AMOUNT = type(uint256).max; string constant NAME = "Fatso Test Name"; string constant SYMBOL = "FTSOTST"; function setUp() public { authority = new GhostAuthority( DEPLOYER, DEPLOYER, DEPLOYER, VAULT ); token = new Fatso(address(authority), NAME, SYMBOL); initializePermit(address(token), AMOUNT, MAX_AMOUNT); initializeAllowance(ALICE, BOB, address(token), AMOUNT, MAX_AMOUNT, AMOUNT); initializeTransfer(ALICE, BOB, address(token), AMOUNT, MAX_AMOUNT); } function test_mint_couldHappenFromVault() public { uint256 totalSupply = token.totalSupply(); vm.prank(VAULT); token.mint(ALICE, AMOUNT); assertEq(token.totalSupply(), totalSupply + AMOUNT); } function test_mint_couldNotMintFromArbitraryAccount(address who) public { vm.assume(who != VAULT); vm.expectRevert(); vm.prank(who); token.mint(ALICE, AMOUNT); } function test_correctlyConstructsAnERC20() public view { assertEq(token.name(), NAME); assertEq(token.symbol(), SYMBOL); assertEq(token.decimals(), 9); } function test_mint_couldBeDoneByVault() public { assertEq(token.balanceOf(BOB), 0); vm.prank(VAULT); token.mint(BOB, AMOUNT); assertEq(token.balanceOf(BOB), AMOUNT); } function test_mint_couldNotBeDoneByArbitraryAccount() public { vm.expectRevert(GhostAccessControlled.Unauthorized.selector); vm.prank(DEPLOYER); token.mint(BOB, AMOUNT); assertEq(token.balanceOf(BOB), 0); } function test_mint_totalSupplyIncreases() public { assertEq(token.totalSupply(), 0); vm.prank(VAULT); token.mint(BOB, AMOUNT); assertEq(token.totalSupply(), AMOUNT); } function test_burn_totalSupplyReduces() public { _mintTokens(BOB, AMOUNT); vm.prank(BOB); token.burn(AMOUNT); assertEq(token.totalSupply(), 0); } function test_burn_cannotExceedTotalSupply() public { _mintTokens(BOB, AMOUNT); vm.expectRevert(); vm.prank(BOB); token.burn(AMOUNT + 1); assertEq(token.totalSupply(), AMOUNT); } function _mintTokens(address who, uint256 value) internal { uint256 totalSupply = token.totalSupply(); vm.prank(VAULT); token.mint(who, value); assertEq(token.totalSupply(), totalSupply + value); } function _mintTransferTokens(address who, uint256 value) internal override { _mintTokens(who, value); } function _mintAllowanceTokens(address who, uint256 value) internal override { _mintTokens(who, value); } function _mintPermitTokens(address who, uint256 value) internal override { _mintTokens(who, value); } function _getCurrentTotalSupply() internal override view returns (uint256) { return token.totalSupply(); } }