Skip to content

Commit

Permalink
tests: unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
0xtekgrinder committed Jul 23, 2024
1 parent 1059b9b commit d5630e1
Show file tree
Hide file tree
Showing 23 changed files with 1,033 additions and 0 deletions.
23 changes: 23 additions & 0 deletions test/BaseTest.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// SPDX-License-Identifier: Unlicensed
pragma solidity 0.8.26;

import "forge-std/Test.sol";
import "utils/src/CommonUtils.sol";
import { IERC20 } from "forge-std/interfaces/IERC20.sol";

contract BaseTest is Test, CommonUtils {
// Useful addresses
address public alice = makeAddr("alice");
address public bob = makeAddr("bob");
address public integrator = makeAddr("integrator");
address public keeper = makeAddr("keeper");
address public developer = makeAddr("developer");

function setUp() public virtual {
vm.label(alice, "alice");
vm.label(bob, "bob");
vm.label(integrator, "integrator");
vm.label(keeper, "keeper");
vm.label(developer, "developer");
}
}
6 changes: 6 additions & 0 deletions test/Constants.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// SPDX-License-Identifier: Unlicensed
pragma solidity 0.8.26;

uint256 constant CHAIN_SOURCE = 1;
address constant ONEINCH_ROUTER = 0x111111125421cA6dc452d289314280a0f8842A65;
address constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
42 changes: 42 additions & 0 deletions test/ERC4626StrategyTest.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.26;

import "./BaseTest.t.sol";
import "./Constants.t.sol";
import "../contracts/utils/Errors.sol";
import { IAccessControl } from "oz/access/AccessControl.sol";
import { ERC4626Strategy, BaseStrategy, ERC4626 } from "../contracts/ERC4626Strategy.sol";

contract ERC4626StrategyTest is BaseTest {
ERC4626Strategy public strategy;
address public asset;
address public strategyAsset;

function setUp() public virtual override {
super.setUp();

vm.createSelectFork("mainnet", 20363172);

asset = _chainToContract(CHAIN_SOURCE, ContractType.AgUSD);
strategyAsset = _chainToContract(CHAIN_SOURCE, ContractType.StUSD);

strategy = new ERC4626Strategy(
BaseStrategy.ConstructorArgs(
10000, // 10%
20000, // 20%
integrator,
developer,
keeper,
developer,
integrator,
ONEINCH_ROUTER,
ONEINCH_ROUTER,
1 weeks,
"stUSD Strategy",
"stUSDStrat",
asset,
strategyAsset
)
);
}
}
13 changes: 13 additions & 0 deletions test/mock/MockRouter.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// SPDX-License-Identifier: Unlicensed
pragma solidity 0.8.26;

import { SafeERC20, IERC20 } from "oz/token/ERC20/utils/SafeERC20.sol";

contract MockRouter {
using SafeERC20 for IERC20;

function swap(uint256 amountIn, address tokenIn, uint256 amountOut, address tokenOut) external {
IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);
IERC20(tokenOut).safeTransfer(msg.sender, amountOut);
}
}
Empty file removed test/unit/.gitkeep
Empty file.
48 changes: 48 additions & 0 deletions test/unit/Accumulate.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// SPDX-License-Identifier: Unlicensed
pragma solidity 0.8.26;

import "../ERC4626StrategyTest.t.sol";

contract AccumulateTest is ERC4626StrategyTest {
function test_accumulate_Normal() public {
deal(asset, alice, 100e18);

vm.startPrank(alice);
IERC20(asset).approve(address(strategy), 100e18);
strategy.deposit(100e18, alice);
vm.stopPrank();
uint256 balance = ERC4626(strategyAsset).balanceOf(address(strategy));
uint256 lastTotalAssets = strategy.lastTotalAssets();
vm.warp(block.timestamp + 1 weeks);

uint256 totalAssets = strategy.totalAssets();
strategy.accumulate();

uint256 feeShares = strategy.convertToShares(
((totalAssets - lastTotalAssets) * strategy.performanceFee()) / strategy.BPS()
);
uint256 developerFeeShares = (feeShares * strategy.developerFee()) / strategy.BPS();

assertEq(strategy.lastTotalAssets(), ERC4626(strategyAsset).convertToAssets(balance));
assertEq(strategy.balanceOf(strategy.integratorFeeRecipient()), feeShares - developerFeeShares);
assertEq(strategy.balanceOf(strategy.developerFeeRecipient()), developerFeeShares);
}

function test_accumulate_NegativeProfit() public {
deal(asset, alice, 100e18);

vm.startPrank(alice);
IERC20(asset).approve(address(strategy), 100e18);
strategy.deposit(100e18, alice);
vm.stopPrank();
uint256 balance = ERC4626(strategyAsset).balanceOf(address(strategy));
uint256 lastTotalAssets = strategy.lastTotalAssets();
vm.warp(block.timestamp + 1 weeks);

vm.mockCall(strategyAsset, abi.encodeWithSelector(IERC20.balanceOf.selector), abi.encode(9e18));
strategy.accumulate();

assertEq(strategy.balanceOf(strategy.integratorFeeRecipient()), 0);
assertEq(strategy.balanceOf(strategy.developerFeeRecipient()), 0);
}
}
241 changes: 241 additions & 0 deletions test/unit/Constructor.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
// SPDX-License-Identifier: Unlicensed
pragma solidity 0.8.26;

import "../ERC4626StrategyTest.t.sol";

contract ConstructorTest is ERC4626StrategyTest {
function test_constructor_Normal() public {
assertEq(strategy.vestingPeriod(), 1 weeks);
assertEq(strategy.performanceFee(), 10_000);
assertEq(strategy.developerFee(), 20_000);
assertEq(strategy.developerFeeRecipient(), developer);
assertEq(strategy.integratorFeeRecipient(), integrator);
assertEq(strategy.swapRouter(), ONEINCH_ROUTER);
assertEq(strategy.tokenTransferAddress(), ONEINCH_ROUTER);
assertEq(strategy.STRATEGY_ASSET(), strategyAsset);
assertEq(strategy.decimals(), 18);
assertEq(strategy.name(), "stUSD Strategy");
assertEq(strategy.symbol(), "stUSDStrat");
assertEq(strategy.lockedProfit(), 0);
}

function test_constructor_CorrectRoles() public {
assertTrue(strategy.hasRole(strategy.DEVELOPER_ROLE(), developer));
assertTrue(strategy.hasRole(strategy.INTEGRATOR_ROLE(), integrator));
assertTrue(strategy.hasRole(strategy.KEEPER_ROLE(), keeper));

assertEq(strategy.getRoleAdmin(strategy.DEVELOPER_ROLE()), strategy.DEVELOPER_ROLE());
assertEq(strategy.getRoleAdmin(strategy.INTEGRATOR_ROLE()), strategy.INTEGRATOR_ROLE());
assertEq(strategy.getRoleAdmin(strategy.KEEPER_ROLE()), strategy.DEVELOPER_ROLE());
}

function test_constructor_DifferentDecimals() public {
vm.mockCall(asset, abi.encodeWithSelector(IERC20.decimals.selector), abi.encode(2));
strategy = new ERC4626Strategy(
BaseStrategy.ConstructorArgs(
10000, // 10%
20000, // 20%
integrator,
developer,
keeper,
developer,
integrator,
ONEINCH_ROUTER,
ONEINCH_ROUTER,
1 weeks,
"stUSD Strategy",
"stUSDStrat",
asset,
strategyAsset
)
);

assertEq(strategy.decimals(), 18);
}

function test_constructor_MaxPerformanceFee() public {
vm.expectRevert(InvalidFee.selector);
strategy = new ERC4626Strategy(
BaseStrategy.ConstructorArgs(
100_001, // 100.001%
20_000, // 20%
integrator,
developer,
keeper,
developer,
integrator,
ONEINCH_ROUTER,
ONEINCH_ROUTER,
1 weeks,
"stUSD Strategy",
"stUSDStrat",
asset,
strategyAsset
)
);
}

function test_constructor_MaxDeveloperFee() public {
vm.expectRevert(InvalidFee.selector);
strategy = new ERC4626Strategy(
BaseStrategy.ConstructorArgs(
100_000, // 100%
50_001, // 20%
integrator,
developer,
keeper,
developer,
integrator,
ONEINCH_ROUTER,
ONEINCH_ROUTER,
1 weeks,
"stUSD Strategy",
"stUSDStrat",
asset,
strategyAsset
)
);
}

function test_constructor_ZeroAdress() public {
vm.expectRevert(ZeroAddress.selector);
strategy = new ERC4626Strategy(
BaseStrategy.ConstructorArgs(
10000, // 10%
20_000, // 20%
address(0),
developer,
keeper,
developer,
integrator,
ONEINCH_ROUTER,
ONEINCH_ROUTER,
1 weeks,
"stUSD Strategy",
"stUSDStrat",
asset,
strategyAsset
)
);

vm.expectRevert(ZeroAddress.selector);
strategy = new ERC4626Strategy(
BaseStrategy.ConstructorArgs(
10000, // 10%
20_000, // 20%
integrator,
address(0),
keeper,
developer,
integrator,
ONEINCH_ROUTER,
ONEINCH_ROUTER,
1 weeks,
"stUSD Strategy",
"stUSDStrat",
asset,
strategyAsset
)
);

vm.expectRevert(ZeroAddress.selector);
strategy = new ERC4626Strategy(
BaseStrategy.ConstructorArgs(
10000, // 10%
20_000, // 20%
integrator,
developer,
address(0),
developer,
integrator,
ONEINCH_ROUTER,
ONEINCH_ROUTER,
1 weeks,
"stUSD Strategy",
"stUSDStrat",
asset,
strategyAsset
)
);

vm.expectRevert(ZeroAddress.selector);
strategy = new ERC4626Strategy(
BaseStrategy.ConstructorArgs(
10000, // 10%
20_000, // 20%
integrator,
developer,
keeper,
address(0),
integrator,
ONEINCH_ROUTER,
ONEINCH_ROUTER,
1 weeks,
"stUSD Strategy",
"stUSDStrat",
asset,
strategyAsset
)
);

vm.expectRevert(ZeroAddress.selector);
strategy = new ERC4626Strategy(
BaseStrategy.ConstructorArgs(
10000, // 10%
20_000, // 20%
integrator,
developer,
keeper,
developer,
address(0),
ONEINCH_ROUTER,
ONEINCH_ROUTER,
1 weeks,
"stUSD Strategy",
"stUSDStrat",
asset,
strategyAsset
)
);

vm.expectRevert(ZeroAddress.selector);
strategy = new ERC4626Strategy(
BaseStrategy.ConstructorArgs(
10000, // 10%
20_000, // 20%
integrator,
developer,
keeper,
developer,
integrator,
address(0),
ONEINCH_ROUTER,
1 weeks,
"stUSD Strategy",
"stUSDStrat",
asset,
strategyAsset
)
);

vm.expectRevert(ZeroAddress.selector);
strategy = new ERC4626Strategy(
BaseStrategy.ConstructorArgs(
10000, // 10%
20_000, // 20%
integrator,
developer,
keeper,
developer,
integrator,
ONEINCH_ROUTER,
address(0),
1 weeks,
"stUSD Strategy",
"stUSDStrat",
asset,
strategyAsset
)
);
}
}
Loading

0 comments on commit d5630e1

Please sign in to comment.