Skip to content

Commit

Permalink
93.9% coverage for pUSD - rest is just assembly
Browse files Browse the repository at this point in the history
  • Loading branch information
ungaro committed Nov 14, 2024
1 parent b00649d commit 013f0eb
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 3 deletions.
7 changes: 4 additions & 3 deletions nest/src/token/pUSD.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import { AccessControlUpgradeable } from "@openzeppelin/contracts-upgradeable/ac
import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import { ERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";

import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import { ERC4626Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC4626Upgradeable.sol";
import { IAccessControl } from "@openzeppelin/contracts/access/IAccessControl.sol";
import { IERC20 } from "@openzeppelin/contracts/interfaces/IERC20.sol";
import { IERC20Metadata } from "@openzeppelin/contracts/interfaces/IERC20Metadata.sol";

import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";

import { ComponentToken } from "../ComponentToken.sol";
import { IComponentToken } from "../interfaces/IComponentToken.sol";
import { console } from "forge-std/console.sol";
Expand Down Expand Up @@ -170,7 +170,8 @@ contract pUSD is Initializable, ERC20Upgradeable, AccessControlUpgradeable, UUPS
function supportsInterface(
bytes4 interfaceId
) public view virtual override(AccessControlUpgradeable, ComponentToken) returns (bool) {
return super.supportsInterface(interfaceId);
return interfaceId == type(IERC20).interfaceId || interfaceId == type(IAccessControl).interfaceId
|| super.supportsInterface(interfaceId);
}

}
104 changes: 104 additions & 0 deletions nest/test/pUSD.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { MockVault } from "../src/mocks/MockVault.sol";
import { pUSD } from "../src/token/pUSD.sol";

import { IAccessControl } from "@openzeppelin/contracts/access/IAccessControl.sol";

import { IERC4626 } from "@openzeppelin/contracts/interfaces/IERC4626.sol";
import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
Expand Down Expand Up @@ -36,6 +38,9 @@ contract pUSDTest is Test {
address public owner;
address public user1;
address public user2;
// Make sure the event matches the contract exactly

event VaultChanged(MockVault indexed oldVault, MockVault indexed newVault);

function setUp() public {
owner = address(this);
Expand Down Expand Up @@ -117,4 +122,103 @@ contract pUSDTest is Test {
assertEq(asset.balanceOf(address(vault)), amount);
}

function testSetVault() public {
// Create a new mock vault
MockVault newVault = new MockVault();

// Try to set vault without proper role - should revert
vm.startPrank(user1);
vm.expectRevert(
abi.encodeWithSelector(
IAccessControl.AccessControlUnauthorizedAccount.selector, user1, token.VAULT_ADMIN_ROLE()
)
);
token.setVault(address(newVault));
vm.stopPrank();

// Grant VAULT_ADMIN_ROLE to the test contract
bytes32 vaultAdminRole = token.VAULT_ADMIN_ROLE();
token.grantRole(vaultAdminRole, address(this));

// Set vault with proper role
address oldVault = address(token.vault());

// Expect the VaultChanged event with the correct address format
//vm.expectEmit(true, true, true, true, address(token));
emit VaultChanged(MockVault(oldVault), newVault);

token.setVault(address(newVault));

// Verify the vault was updated
assertEq(address(token.vault()), address(newVault));
}

// Add this event definition at the contract level
//event VaultChanged(address indexed oldVault, address indexed newVault);

function testVault() public {
// Verify the vault address matches what we set in setUp
assertEq(address(token.vault()), address(vault));
}

function testTransferFrom() public {
uint256 amount = 100e6;

// Setup: user1 deposits tokens
vm.startPrank(user1);
token.deposit(amount, user1, user1);

// Approve user2 to spend tokens
token.approve(user2, amount);
vm.stopPrank();

// user2 transfers tokens from user1 to themselves
vm.prank(user2);
token.transferFrom(user1, user2, amount);

// Verify balances
assertEq(token.balanceOf(user1), 0);
assertEq(token.balanceOf(user2), amount);

// Verify allowance was decreased
assertEq(token.allowance(user1, user2), 0);
}

function testTransferFromWithMaxApproval() public {
uint256 amount = 100e6;

// Setup: user1 deposits tokens
vm.startPrank(user1);
token.deposit(amount, user1, user1);

// Approve user2 to spend max tokens
token.approve(user2, type(uint256).max);
vm.stopPrank();

// user2 transfers tokens from user1 to themselves
vm.prank(user2);
token.transferFrom(user1, user2, amount);

// Verify balances
assertEq(token.balanceOf(user1), 0);
assertEq(token.balanceOf(user2), amount);

// Verify max allowance remains unchanged
assertEq(token.allowance(user1, user2), type(uint256).max);
}

function testSupportsInterface() public {
// Test for ERC20 interface
bytes4 erc20InterfaceId = type(IERC20).interfaceId;
assertTrue(token.supportsInterface(erc20InterfaceId));

// Test for AccessControl interface
bytes4 accessControlInterfaceId = type(IAccessControl).interfaceId;
assertTrue(token.supportsInterface(accessControlInterfaceId));

// Test for non-supported interface
bytes4 randomInterfaceId = bytes4(keccak256("random()"));
assertFalse(token.supportsInterface(randomInterfaceId));
}

}

0 comments on commit 013f0eb

Please sign in to comment.