Skip to content

Commit

Permalink
aggregate token tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ungaro committed Dec 6, 2024
1 parent 37792d9 commit 5a751b9
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 43 deletions.
5 changes: 2 additions & 3 deletions nest/script/DeployNestContracts.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ import { NestStaking } from "../src/NestStaking.sol";
import { IComponentToken } from "../src/interfaces/IComponentToken.sol";
import { AggregateTokenProxy } from "../src/proxy/AggregateTokenProxy.sol";
import { NestStakingProxy } from "../src/proxy/NestStakingProxy.sol";
import { pUSD } from "../src/token/pUSD.sol";

import { pUSDProxy } from "../src/proxy/pUSDProxy.sol";
import { pUSD } from "../src/token/pUSD.sol";

// Concrete implementation of ComponentToken
contract ConcreteComponentToken is ComponentToken {
Expand Down Expand Up @@ -45,8 +46,6 @@ contract DeployNestContracts is Script, Test {
function run() external {
vm.startBroadcast(NEST_ADMIN_ADDRESS);



AggregateToken aggregateToken = new AggregateToken();
AggregateTokenProxy aggregateTokenProxy = new AggregateTokenProxy(
address(aggregateToken),
Expand Down
5 changes: 0 additions & 5 deletions nest/src/AggregateToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,12 @@ contract AggregateToken is ComponentToken, IAggregateToken, ERC1155Holder {
bytes32 private constant AGGREGATE_TOKEN_STORAGE_LOCATION =
0xd3be8f8d43881152ac95daeff8f4c57e01616286ffd74814a5517f422a6b6200;


function _getAggregateTokenStorage() private pure returns (AggregateTokenStorage storage $) {
assembly {
$.slot := AGGREGATE_TOKEN_STORAGE_LOCATION
}
}



// Constants

/// @notice Role for the price updater of the AggregateToken
Expand Down Expand Up @@ -269,8 +266,6 @@ contract AggregateToken is ComponentToken, IAggregateToken, ERC1155Holder {
emit ComponentTokenUnlisted(componentToken);
}



/**
* @notice Buy ComponentToken using `asset`
* @dev Only the owner can call this function, will revert if
Expand Down
129 changes: 94 additions & 35 deletions nest/test/AggregateToken.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,49 +2,18 @@
pragma solidity ^0.8.25;

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";
import { Strings } from "@openzeppelin/contracts/utils/Strings.sol";
import { Test } from "forge-std/Test.sol";
import { console } from "forge-std/console.sol";

import { AggregateToken } from "../src/AggregateToken.sol";
import { IComponentToken } from "../src/interfaces/IComponentToken.sol";

import { AggregateTokenProxy } from "../src/proxy/AggregateTokenProxy.sol";
import { Test } from "forge-std/Test.sol";
import { console } from "forge-std/console.sol";

contract MockUSDC is ERC20 {

constructor() ERC20("Invalid Token", "INVALID") {
_mint(msg.sender, 1_000_000 * 10 ** decimals());
}

function decimals() public pure override returns (uint8) {
return 12; // Different from USDC's 6 decimals
}

function mint(address to, uint256 amount) external {
_mint(to, amount);
}

}

contract MockInvalidToken is ERC20 {

constructor() ERC20("Invalid Token", "INVALID") {
_mint(msg.sender, 1_000_000 * 10 ** decimals());
}

function decimals() public pure override returns (uint8) {
return 12; // Different from USDC's 6 decimals
}

function mint(address to, uint256 amount) external {
_mint(to, amount);
}

}
import { MockInvalidToken } from "../src/mocks/MockInvalidToken.sol";
import { MockUSDC } from "../src/mocks/MockUSDC.sol";

contract AggregateTokenTest is Test {

Expand All @@ -65,6 +34,9 @@ contract AggregateTokenTest is Test {
event ComponentTokenSold(
address indexed seller, IComponentToken indexed componentToken, uint256 componentTokenAmount, uint256 assets
);
event Paused();
event Unpaused();
event ComponentTokenRemoved(IComponentToken indexed componentToken);

function setUp() public {
owner = makeAddr("owner");
Expand Down Expand Up @@ -99,6 +71,93 @@ contract AggregateTokenTest is Test {
usdc.approve(address(token), type(uint256).max);
}

function testAddComponentToken() public {
vm.startPrank(owner);

// Should succeed first time
token.addComponentToken(IComponentToken(address(newUsdc)));

// Should fail second time
vm.expectRevert(
abi.encodeWithSelector(
AggregateToken.ComponentTokenAlreadyListed.selector, IComponentToken(address(newUsdc))
)
);
token.addComponentToken(IComponentToken(address(newUsdc)));

vm.stopPrank();
}

function testRemoveComponentToken() public {
vm.startPrank(owner);

// Add a token first
token.addComponentToken(IComponentToken(address(newUsdc)));

// Should fail when trying to remove current asset
vm.expectRevert(
abi.encodeWithSelector(AggregateToken.ComponentTokenIsAsset.selector, IComponentToken(address(usdc)))
);
token.removeComponentToken(IComponentToken(address(usdc)));

// Should succeed with non-asset token
token.removeComponentToken(IComponentToken(address(newUsdc)));

// Should fail when trying to remove non-existent token
vm.expectRevert(
abi.encodeWithSelector(AggregateToken.ComponentTokenNotListed.selector, IComponentToken(address(newUsdc)))
);
token.removeComponentToken(IComponentToken(address(newUsdc)));

vm.stopPrank();
}

function testPauseUnpause() public {
vm.startPrank(owner);

// Should start unpaused
assertFalse(token.isPaused());

// Should pause
vm.expectEmit(address(token));
emit Paused();
token.pause();
assertTrue(token.isPaused());

// Should fail when already paused
vm.expectRevert(AggregateToken.AlreadyPaused.selector);
token.pause();

// Should unpause
vm.expectEmit(address(token));
emit Unpaused();
token.unpause();
assertFalse(token.isPaused());

// Should fail when already unpaused
vm.expectRevert(AggregateToken.NotPaused.selector);
token.unpause();

vm.stopPrank();
}

function testSetPrices() public {
// Grant price updater role
bytes32 priceUpdaterRole = token.PRICE_UPDATER_ROLE();
vm.startPrank(owner);
token.grantRole(priceUpdaterRole, owner);

// Test ask price
token.setAskPrice(2e18);
assertEq(token.getAskPrice(), 2e18);

// Test bid price
token.setBidPrice(1.5e18);
assertEq(token.getBidPrice(), 1.5e18);

vm.stopPrank();
}

// Helper function for access control error message
function accessControlErrorMessage(address account, bytes32 role) internal pure returns (bytes memory) {
return abi.encodePacked(
Expand Down

0 comments on commit 5a751b9

Please sign in to comment.