133 lines
5.6 KiB
Solidity
133 lines
5.6 KiB
Solidity
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
pragma solidity ^0.8.19;
|
|
|
|
import "forge-std/Test.sol";
|
|
import "forge-std/console.sol";
|
|
import {TwabController} from "pt-v5-twab-controller/TwabController.sol";
|
|
import {PoolAddress, PoolKey} from "@aperture/uni-v3-lib/PoolAddress.sol";
|
|
import "@uniswap-v3-core/interfaces/IUniswapV3Factory.sol";
|
|
import "@uniswap-v3-core/interfaces/IUniswapV3Pool.sol";
|
|
import "../src/interfaces/IWETH9.sol";
|
|
import "../src/Harb.sol";
|
|
import {BaseLineLP} from "../src/BaseLineLP.sol";
|
|
import {Stake, ExceededAvailableStake} from "../src/Stake.sol";
|
|
|
|
address constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
|
|
address constant V3_FACTORY = 0x1F98431c8aD98523631AE4a59f267346ea31F984;
|
|
address constant TAX_POOL = address(2);
|
|
// default fee of 1%
|
|
uint24 constant FEE = uint24(10_000);
|
|
|
|
contract HarbTest is Test {
|
|
uint256 mainnetFork;
|
|
IWETH9 weth;
|
|
Harb harb;
|
|
IUniswapV3Factory factory;
|
|
Stake stake;
|
|
BaseLineLP liquidityManager;
|
|
|
|
function setUp() public {
|
|
mainnetFork = vm.createFork(vm.envString("ETH_NODE_URI_MAINNET"), 19461248);
|
|
vm.selectFork(mainnetFork);
|
|
weth = IWETH9(WETH);
|
|
TwabController tc = new TwabController(60 * 60 * 24, uint32(block.timestamp));
|
|
harb = new Harb("HARB", "HARB", V3_FACTORY, WETH, tc);
|
|
factory = IUniswapV3Factory(V3_FACTORY);
|
|
factory.createPool(address(weth), address(harb), FEE);
|
|
stake = new Stake(address(harb));
|
|
harb.setStakingPool(address(stake));
|
|
liquidityManager = new BaseLineLP(V3_FACTORY, WETH, address(harb));
|
|
harb.setLiquidityManager(address(liquidityManager));
|
|
}
|
|
|
|
function test_MintStakeUnstake(address account, uint256 amount) public {
|
|
vm.assume(amount > 10000);
|
|
vm.assume(amount < 2 ** 93); // TWAB limit = 2**96
|
|
vm.assume(account != address(0));
|
|
vm.assume(account != address(1)); // TWAB sponsorship address
|
|
vm.assume(account != address(2)); // tax pool address
|
|
vm.assume(account != address(harb));
|
|
vm.assume(account != address(stake));
|
|
|
|
// test mint
|
|
uint256 totalSupplyBefore = harb.totalSupply();
|
|
uint256 balanceBefore = harb.balanceOf(account);
|
|
harb.setLiquidityManager(account);
|
|
vm.prank(account);
|
|
harb.mint(amount);
|
|
uint256 totalAfter = harb.totalSupply();
|
|
assertEq(totalAfter, totalSupplyBefore + amount, "total supply should match");
|
|
assertEq(harb.balanceOf(account), balanceBefore + amount, "balance should match");
|
|
|
|
// test UBI title
|
|
{
|
|
// prepare UBI title
|
|
vm.prank(account);
|
|
harb.mint(amount * 4);
|
|
address alice = makeAddr("alice");
|
|
vm.prank(account);
|
|
harb.transfer(alice, amount);
|
|
vm.prank(alice);
|
|
harb.transfer(account, amount);
|
|
// check ubi title
|
|
(uint256 titleSumTax, uint256 titleTime) = harb.ubiTitles(account);
|
|
assertEq(titleSumTax, 0, "no taxes paid yet");
|
|
assertEq(block.timestamp, titleTime, "title start time should match");
|
|
}
|
|
|
|
// test stake
|
|
{
|
|
// get some stake
|
|
assertEq(stake.outstandingStake(), 0, "init failure");
|
|
vm.prank(account);
|
|
harb.approve(address(stake), amount);
|
|
uint256[] memory empty;
|
|
vm.prank(account);
|
|
stake.snatch(amount, account, 1, empty);
|
|
assertEq(harb.totalSupply(), totalAfter * 5, "total supply should match after stake");
|
|
assertEq(harb.balanceOf(account), amount * 4, "balance should match after stake");
|
|
assertEq(harb.balanceOf(address(stake)), amount, "balance should match after stake");
|
|
// check stake position
|
|
(uint256 share, address owner, uint32 creationTime, uint32 lastTaxTime, uint32 taxRate) = stake.positions(0);
|
|
assertEq(share, stake.totalSupply() / 5, "share should match");
|
|
assertEq(owner, account, "owners should match");
|
|
assertEq(creationTime, block.timestamp, "time should match");
|
|
assertEq(lastTaxTime, block.timestamp, "tax time should match");
|
|
assertEq(taxRate, 1, "tax rate should match");
|
|
}
|
|
|
|
// test stake when stake full
|
|
{
|
|
uint256[] memory empty;
|
|
vm.expectRevert();
|
|
//vm.expectRevert(abi.encodeWithSelector(ExceededAvailableStake.selector, account, amount, 0));
|
|
vm.prank(account);
|
|
stake.snatch(amount, account, 2, empty);
|
|
}
|
|
|
|
// test unstake
|
|
{
|
|
// advance the time
|
|
uint256 timeBefore = block.timestamp;
|
|
vm.warp(timeBefore + 60 * 60 * 24 * 4);
|
|
uint256 taxDue = stake.taxDue(0, 60 * 60 * 24 * 3);
|
|
|
|
uint256 sumTaxCollectedBefore = harb.sumTaxCollected();
|
|
vm.prank(account);
|
|
stake.exitPosition(0);
|
|
assertApproxEqRel(harb.balanceOf(account), amount * 5 - taxDue, 1e14, "account balance should match");
|
|
assertEq(harb.balanceOf(TAX_POOL), taxDue, "tax pool balance should match");
|
|
assertEq(sumTaxCollectedBefore + taxDue, harb.sumTaxCollected(), "collected tax should have increased");
|
|
}
|
|
|
|
// claim tax
|
|
{
|
|
balanceBefore = harb.balanceOf(account);
|
|
uint256 ubiDue = harb.getUbiDue(account);
|
|
vm.prank(account);
|
|
harb.claimUbi(account);
|
|
assertFalse(ubiDue == 0, "Not UBI paid");
|
|
assertEq(balanceBefore + ubiDue, harb.balanceOf(account), "ubi should match");
|
|
}
|
|
}
|
|
}
|