feat: add valueless mock USDC
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity 0.8.35;
|
||||
|
||||
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
|
||||
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
|
||||
|
||||
/// @notice Educational mock token with no monetary value. Never use as real USDC.
|
||||
contract MockUSDC is ERC20, Ownable {
|
||||
constructor(address initialOwner) ERC20("Mock USD Coin", "mUSDC") Ownable(initialOwner) {}
|
||||
|
||||
function decimals() public pure override returns (uint8) {
|
||||
return 6;
|
||||
}
|
||||
|
||||
function mint(address to, uint256 amount) external onlyOwner {
|
||||
_mint(to, amount);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity 0.8.35;
|
||||
|
||||
import {Test} from "forge-std/Test.sol";
|
||||
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
|
||||
import {MockUSDC} from "../src/MockUSDC.sol";
|
||||
|
||||
contract MockUSDCTest is Test {
|
||||
MockUSDC internal token;
|
||||
address internal constant STRANGER = address(0xBEEF);
|
||||
address internal constant RECIPIENT = address(0xCAFE);
|
||||
address internal constant SPENDER = address(0xD00D);
|
||||
|
||||
function setUp() public {
|
||||
token = new MockUSDC(address(this));
|
||||
}
|
||||
|
||||
function testMetadataUsesSixDecimalMockUSDC() public view {
|
||||
assertEq(token.name(), "Mock USD Coin");
|
||||
assertEq(token.symbol(), "mUSDC");
|
||||
assertEq(token.decimals(), 6);
|
||||
}
|
||||
|
||||
function testInitialSupplyIsZero() public view {
|
||||
assertEq(token.totalSupply(), 0);
|
||||
}
|
||||
|
||||
function testMintMintsToRecipientWhenCalledByOwner() public {
|
||||
token.mint(RECIPIENT, 1_250_000);
|
||||
|
||||
assertEq(token.totalSupply(), 1_250_000);
|
||||
assertEq(token.balanceOf(RECIPIENT), 1_250_000);
|
||||
}
|
||||
|
||||
function testMintRevertsWhenCalledByNonOwner() public {
|
||||
vm.prank(STRANGER);
|
||||
vm.expectRevert(abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, STRANGER));
|
||||
token.mint(RECIPIENT, 1);
|
||||
}
|
||||
|
||||
function testTransferMovesMintedBalance() public {
|
||||
token.mint(address(this), 1_250_000);
|
||||
|
||||
token.transfer(RECIPIENT, 250_000);
|
||||
|
||||
assertEq(token.balanceOf(address(this)), 1_000_000);
|
||||
assertEq(token.balanceOf(RECIPIENT), 250_000);
|
||||
}
|
||||
|
||||
function testApproveSetsAllowanceForSpender() public {
|
||||
token.approve(SPENDER, 750_000);
|
||||
|
||||
assertEq(token.allowance(address(this), SPENDER), 750_000);
|
||||
}
|
||||
|
||||
function testConstructorRevertsForZeroInitialOwner() public {
|
||||
vm.expectRevert(abi.encodeWithSelector(Ownable.OwnableInvalidOwner.selector, address(0)));
|
||||
new MockUSDC(address(0));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user